]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
added an experimental alternate code path in DPSOFTRAST where all the
[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 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 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)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 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"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 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)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 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"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 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)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 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"};
78 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"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 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"};
81 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"};
82 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"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 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)"};
91 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)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 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."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 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."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 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"};
114 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"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 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"};
120
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129
130 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)"};
131 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"};
132
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 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)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 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)"};
149 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)"};
150 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)"};
151 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)"};
152 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)"};
153 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)"};
154 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)"};
155 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)"};
156
157 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)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 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"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 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)"};
181
182 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"};
183
184 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"};
185
186 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
187
188 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
189 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"};
190 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
191 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
192 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
193 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
194 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)"};
195 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
196 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
197
198 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
199 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"};
200
201 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)"};
202
203 extern cvar_t v_glslgamma;
204
205 extern qboolean v_flipped_state;
206
207 static struct r_bloomstate_s
208 {
209         qboolean enabled;
210         qboolean hdr;
211
212         int bloomwidth, bloomheight;
213
214         int screentexturewidth, screentextureheight;
215         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
216
217         int bloomtexturewidth, bloomtextureheight;
218         rtexture_t *texture_bloom;
219
220         // arrays for rendering the screen passes
221         float screentexcoord2f[8];
222         float bloomtexcoord2f[8];
223         float offsettexcoord2f[8];
224
225         r_viewport_t viewport;
226 }
227 r_bloomstate;
228
229 r_waterstate_t r_waterstate;
230
231 /// shadow volume bsp struct with automatically growing nodes buffer
232 svbsp_t r_svbsp;
233
234 rtexture_t *r_texture_blanknormalmap;
235 rtexture_t *r_texture_white;
236 rtexture_t *r_texture_grey128;
237 rtexture_t *r_texture_black;
238 rtexture_t *r_texture_notexture;
239 rtexture_t *r_texture_whitecube;
240 rtexture_t *r_texture_normalizationcube;
241 rtexture_t *r_texture_fogattenuation;
242 rtexture_t *r_texture_fogheighttexture;
243 rtexture_t *r_texture_gammaramps;
244 unsigned int r_texture_gammaramps_serial;
245 //rtexture_t *r_texture_fogintensity;
246 rtexture_t *r_texture_reflectcube;
247
248 // TODO: hash lookups?
249 typedef struct cubemapinfo_s
250 {
251         char basename[64];
252         rtexture_t *texture;
253 }
254 cubemapinfo_t;
255
256 int r_texture_numcubemaps;
257 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
258
259 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
260 unsigned int r_numqueries;
261 unsigned int r_maxqueries;
262
263 typedef struct r_qwskincache_s
264 {
265         char name[MAX_QPATH];
266         skinframe_t *skinframe;
267 }
268 r_qwskincache_t;
269
270 static r_qwskincache_t *r_qwskincache;
271 static int r_qwskincache_size;
272
273 /// vertex coordinates for a quad that covers the screen exactly
274 extern const float r_screenvertex3f[12];
275 extern const float r_d3dscreenvertex3f[12];
276 const float r_screenvertex3f[12] =
277 {
278         0, 0, 0,
279         1, 0, 0,
280         1, 1, 0,
281         0, 1, 0
282 };
283 const float r_d3dscreenvertex3f[12] =
284 {
285         0, 1, 0,
286         1, 1, 0,
287         1, 0, 0,
288         0, 0, 0
289 };
290
291 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
292 {
293         int i;
294         for (i = 0;i < verts;i++)
295         {
296                 out[0] = in[0] * r;
297                 out[1] = in[1] * g;
298                 out[2] = in[2] * b;
299                 out[3] = in[3];
300                 in += 4;
301                 out += 4;
302         }
303 }
304
305 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
306 {
307         int i;
308         for (i = 0;i < verts;i++)
309         {
310                 out[0] = r;
311                 out[1] = g;
312                 out[2] = b;
313                 out[3] = a;
314                 out += 4;
315         }
316 }
317
318 // FIXME: move this to client?
319 void FOG_clear(void)
320 {
321         if (gamemode == GAME_NEHAHRA)
322         {
323                 Cvar_Set("gl_fogenable", "0");
324                 Cvar_Set("gl_fogdensity", "0.2");
325                 Cvar_Set("gl_fogred", "0.3");
326                 Cvar_Set("gl_foggreen", "0.3");
327                 Cvar_Set("gl_fogblue", "0.3");
328         }
329         r_refdef.fog_density = 0;
330         r_refdef.fog_red = 0;
331         r_refdef.fog_green = 0;
332         r_refdef.fog_blue = 0;
333         r_refdef.fog_alpha = 1;
334         r_refdef.fog_start = 0;
335         r_refdef.fog_end = 16384;
336         r_refdef.fog_height = 1<<30;
337         r_refdef.fog_fadedepth = 128;
338         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
339 }
340
341 static void R_BuildBlankTextures(void)
342 {
343         unsigned char data[4];
344         data[2] = 128; // normal X
345         data[1] = 128; // normal Y
346         data[0] = 255; // normal Z
347         data[3] = 128; // height
348         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
349         data[0] = 255;
350         data[1] = 255;
351         data[2] = 255;
352         data[3] = 255;
353         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
354         data[0] = 128;
355         data[1] = 128;
356         data[2] = 128;
357         data[3] = 255;
358         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359         data[0] = 0;
360         data[1] = 0;
361         data[2] = 0;
362         data[3] = 255;
363         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364 }
365
366 static void R_BuildNoTexture(void)
367 {
368         int x, y;
369         unsigned char pix[16][16][4];
370         // this makes a light grey/dark grey checkerboard texture
371         for (y = 0;y < 16;y++)
372         {
373                 for (x = 0;x < 16;x++)
374                 {
375                         if ((y < 8) ^ (x < 8))
376                         {
377                                 pix[y][x][0] = 128;
378                                 pix[y][x][1] = 128;
379                                 pix[y][x][2] = 128;
380                                 pix[y][x][3] = 255;
381                         }
382                         else
383                         {
384                                 pix[y][x][0] = 64;
385                                 pix[y][x][1] = 64;
386                                 pix[y][x][2] = 64;
387                                 pix[y][x][3] = 255;
388                         }
389                 }
390         }
391         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
392 }
393
394 static void R_BuildWhiteCube(void)
395 {
396         unsigned char data[6*1*1*4];
397         memset(data, 255, sizeof(data));
398         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
399 }
400
401 static void R_BuildNormalizationCube(void)
402 {
403         int x, y, side;
404         vec3_t v;
405         vec_t s, t, intensity;
406 #define NORMSIZE 64
407         unsigned char *data;
408         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
409         for (side = 0;side < 6;side++)
410         {
411                 for (y = 0;y < NORMSIZE;y++)
412                 {
413                         for (x = 0;x < NORMSIZE;x++)
414                         {
415                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
416                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
417                                 switch(side)
418                                 {
419                                 default:
420                                 case 0:
421                                         v[0] = 1;
422                                         v[1] = -t;
423                                         v[2] = -s;
424                                         break;
425                                 case 1:
426                                         v[0] = -1;
427                                         v[1] = -t;
428                                         v[2] = s;
429                                         break;
430                                 case 2:
431                                         v[0] = s;
432                                         v[1] = 1;
433                                         v[2] = t;
434                                         break;
435                                 case 3:
436                                         v[0] = s;
437                                         v[1] = -1;
438                                         v[2] = -t;
439                                         break;
440                                 case 4:
441                                         v[0] = s;
442                                         v[1] = -t;
443                                         v[2] = 1;
444                                         break;
445                                 case 5:
446                                         v[0] = -s;
447                                         v[1] = -t;
448                                         v[2] = -1;
449                                         break;
450                                 }
451                                 intensity = 127.0f / sqrt(DotProduct(v, v));
452                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
453                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
454                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
455                                 data[((side*64+y)*64+x)*4+3] = 255;
456                         }
457                 }
458         }
459         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
460         Mem_Free(data);
461 }
462
463 static void R_BuildFogTexture(void)
464 {
465         int x, b;
466 #define FOGWIDTH 256
467         unsigned char data1[FOGWIDTH][4];
468         //unsigned char data2[FOGWIDTH][4];
469         double d, r, alpha;
470
471         r_refdef.fogmasktable_start = r_refdef.fog_start;
472         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
473         r_refdef.fogmasktable_range = r_refdef.fogrange;
474         r_refdef.fogmasktable_density = r_refdef.fog_density;
475
476         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
477         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
478         {
479                 d = (x * r - r_refdef.fogmasktable_start);
480                 if(developer_extra.integer)
481                         Con_DPrintf("%f ", d);
482                 d = max(0, d);
483                 if (r_fog_exp2.integer)
484                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
485                 else
486                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
487                 if(developer_extra.integer)
488                         Con_DPrintf(" : %f ", alpha);
489                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
490                 if(developer_extra.integer)
491                         Con_DPrintf(" = %f\n", alpha);
492                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
493         }
494
495         for (x = 0;x < FOGWIDTH;x++)
496         {
497                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
498                 data1[x][0] = b;
499                 data1[x][1] = b;
500                 data1[x][2] = b;
501                 data1[x][3] = 255;
502                 //data2[x][0] = 255 - b;
503                 //data2[x][1] = 255 - b;
504                 //data2[x][2] = 255 - b;
505                 //data2[x][3] = 255;
506         }
507         if (r_texture_fogattenuation)
508         {
509                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
510                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
511         }
512         else
513         {
514                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
515                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
516         }
517 }
518
519 static void R_BuildFogHeightTexture(void)
520 {
521         unsigned char *inpixels;
522         int size;
523         int x;
524         int y;
525         int j;
526         float c[4];
527         float f;
528         inpixels = NULL;
529         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
530         if (r_refdef.fogheighttexturename[0])
531                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
532         if (!inpixels)
533         {
534                 r_refdef.fog_height_tablesize = 0;
535                 if (r_texture_fogheighttexture)
536                         R_FreeTexture(r_texture_fogheighttexture);
537                 r_texture_fogheighttexture = NULL;
538                 if (r_refdef.fog_height_table2d)
539                         Mem_Free(r_refdef.fog_height_table2d);
540                 r_refdef.fog_height_table2d = NULL;
541                 if (r_refdef.fog_height_table1d)
542                         Mem_Free(r_refdef.fog_height_table1d);
543                 r_refdef.fog_height_table1d = NULL;
544                 return;
545         }
546         size = image_width;
547         r_refdef.fog_height_tablesize = size;
548         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
549         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
550         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
551         Mem_Free(inpixels);
552         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
553         // average fog color table accounting for every fog layer between a point
554         // and the camera.  (Note: attenuation is handled separately!)
555         for (y = 0;y < size;y++)
556         {
557                 for (x = 0;x < size;x++)
558                 {
559                         Vector4Clear(c);
560                         f = 0;
561                         if (x < y)
562                         {
563                                 for (j = x;j <= y;j++)
564                                 {
565                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
566                                         f++;
567                                 }
568                         }
569                         else
570                         {
571                                 for (j = x;j >= y;j--)
572                                 {
573                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
574                                         f++;
575                                 }
576                         }
577                         f = 1.0f / f;
578                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
579                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
580                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
581                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
582                 }
583         }
584         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
585 }
586
587 //=======================================================================================================================================================
588
589 static const char *builtinshaderstring =
590 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
591 "// written by Forest 'LordHavoc' Hale\n"
592 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
593 "\n"
594 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
595 "# define USEFOG\n"
596 "#endif\n"
597 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
598 "#define USELIGHTMAP\n"
599 "#endif\n"
600 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
601 "#define USEEYEVECTOR\n"
602 "#endif\n"
603 "\n"
604 "#ifdef USESHADOWMAP2D\n"
605 "# ifdef GL_EXT_gpu_shader4\n"
606 "#   extension GL_EXT_gpu_shader4 : enable\n"
607 "# endif\n"
608 "# ifdef GL_ARB_texture_gather\n"
609 "#   extension GL_ARB_texture_gather : enable\n"
610 "# else\n"
611 "#   ifdef GL_AMD_texture_texture4\n"
612 "#     extension GL_AMD_texture_texture4 : enable\n"
613 "#   endif\n"
614 "# endif\n"
615 "#endif\n"
616 "\n"
617 "//#ifdef USESHADOWSAMPLER\n"
618 "//# extension GL_ARB_shadow : enable\n"
619 "//#endif\n"
620 "\n"
621 "//#ifdef __GLSL_CG_DATA_TYPES\n"
622 "//# define myhalf half\n"
623 "//# define myhalf2 half2\n"
624 "//# define myhalf3 half3\n"
625 "//# define myhalf4 half4\n"
626 "//#else\n"
627 "# define myhalf float\n"
628 "# define myhalf2 vec2\n"
629 "# define myhalf3 vec3\n"
630 "# define myhalf4 vec4\n"
631 "//#endif\n"
632 "\n"
633 "#ifdef VERTEX_SHADER\n"
634 "uniform mat4 ModelViewProjectionMatrix;\n"
635 "#endif\n"
636 "\n"
637 "#ifdef MODE_DEPTH_OR_SHADOW\n"
638 "#ifdef VERTEX_SHADER\n"
639 "void main(void)\n"
640 "{\n"
641 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
642 "}\n"
643 "#endif\n"
644 "#else // !MODE_DEPTH_ORSHADOW\n"
645 "\n"
646 "\n"
647 "\n"
648 "\n"
649 "#ifdef MODE_SHOWDEPTH\n"
650 "#ifdef VERTEX_SHADER\n"
651 "void main(void)\n"
652 "{\n"
653 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
654 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
655 "}\n"
656 "#endif\n"
657 "\n"
658 "#ifdef FRAGMENT_SHADER\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FragColor = gl_Color;\n"
662 "}\n"
663 "#endif\n"
664 "#else // !MODE_SHOWDEPTH\n"
665 "\n"
666 "\n"
667 "\n"
668 "\n"
669 "#ifdef MODE_POSTPROCESS\n"
670 "varying vec2 TexCoord1;\n"
671 "varying vec2 TexCoord2;\n"
672 "\n"
673 "#ifdef VERTEX_SHADER\n"
674 "void main(void)\n"
675 "{\n"
676 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
677 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
678 "#ifdef USEBLOOM\n"
679 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
680 "#endif\n"
681 "}\n"
682 "#endif\n"
683 "\n"
684 "#ifdef FRAGMENT_SHADER\n"
685 "uniform sampler2D Texture_First;\n"
686 "#ifdef USEBLOOM\n"
687 "uniform sampler2D Texture_Second;\n"
688 "uniform vec4 BloomColorSubtract;\n"
689 "#endif\n"
690 "#ifdef USEGAMMARAMPS\n"
691 "uniform sampler2D Texture_GammaRamps;\n"
692 "#endif\n"
693 "#ifdef USESATURATION\n"
694 "uniform float Saturation;\n"
695 "#endif\n"
696 "#ifdef USEVIEWTINT\n"
697 "uniform vec4 ViewTintColor;\n"
698 "#endif\n"
699 "//uncomment these if you want to use them:\n"
700 "uniform vec4 UserVec1;\n"
701 "uniform vec4 UserVec2;\n"
702 "// uniform vec4 UserVec3;\n"
703 "// uniform vec4 UserVec4;\n"
704 "// uniform float ClientTime;\n"
705 "uniform vec2 PixelSize;\n"
706 "void main(void)\n"
707 "{\n"
708 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
709 "#ifdef USEBLOOM\n"
710 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
711 "#endif\n"
712 "#ifdef USEVIEWTINT\n"
713 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
714 "#endif\n"
715 "\n"
716 "#ifdef USEPOSTPROCESSING\n"
717 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
718 "// 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"
719 "       float sobel = 1.0;\n"
720 "       // vec2 ts = textureSize(Texture_First, 0);\n"
721 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
722 "       vec2 px = PixelSize;\n"
723 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
724 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
725 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
726 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
727 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
728 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
729 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
730 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
731 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
732 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
733 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
734 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
735 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
736 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
737 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
738 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
739 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
740 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
741 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
742 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
743 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
744 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
745 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
746 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
747 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
748 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
749 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
750 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
751 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
752 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
753 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
754 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
755 "#endif\n"
756 "\n"
757 "#ifdef USESATURATION\n"
758 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
759 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
760 "       // 'vampire sight' effect, wheres red is compensated\n"
761 "       #ifdef SATURATION_REDCOMPENSATE\n"
762 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
763 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
764 "               gl_FragColor.r += rboost;\n"
765 "       #else\n"
766 "               // normal desaturation\n"
767 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
768 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
769 "       #endif\n"
770 "#endif\n"
771 "\n"
772 "#ifdef USEGAMMARAMPS\n"
773 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
774 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
775 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
776 "#endif\n"
777 "}\n"
778 "#endif\n"
779 "#else // !MODE_POSTPROCESS\n"
780 "\n"
781 "\n"
782 "\n"
783 "\n"
784 "#ifdef MODE_GENERIC\n"
785 "#ifdef USEDIFFUSE\n"
786 "varying vec2 TexCoord1;\n"
787 "#endif\n"
788 "#ifdef USESPECULAR\n"
789 "varying vec2 TexCoord2;\n"
790 "#endif\n"
791 "#ifdef VERTEX_SHADER\n"
792 "void main(void)\n"
793 "{\n"
794 "       gl_FrontColor = gl_Color;\n"
795 "#ifdef USEDIFFUSE\n"
796 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
797 "#endif\n"
798 "#ifdef USESPECULAR\n"
799 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
800 "#endif\n"
801 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
802 "}\n"
803 "#endif\n"
804 "\n"
805 "#ifdef FRAGMENT_SHADER\n"
806 "#ifdef USEDIFFUSE\n"
807 "uniform sampler2D Texture_First;\n"
808 "#endif\n"
809 "#ifdef USESPECULAR\n"
810 "uniform sampler2D Texture_Second;\n"
811 "#endif\n"
812 "\n"
813 "void main(void)\n"
814 "{\n"
815 "#ifdef USEVIEWTINT\n"
816 "       gl_FragColor = gl_Color;\n"
817 "#else\n"
818 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
819 "#endif\n"
820 "#ifdef USEDIFFUSE\n"
821 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
822 "#endif\n"
823 "\n"
824 "#ifdef USESPECULAR\n"
825 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
826 "# ifdef USECOLORMAPPING\n"
827 "       gl_FragColor *= tex2;\n"
828 "# endif\n"
829 "# ifdef USEGLOW\n"
830 "       gl_FragColor += tex2;\n"
831 "# endif\n"
832 "# ifdef USEVERTEXTEXTUREBLEND\n"
833 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
834 "# endif\n"
835 "#endif\n"
836 "}\n"
837 "#endif\n"
838 "#else // !MODE_GENERIC\n"
839 "\n"
840 "\n"
841 "\n"
842 "\n"
843 "#ifdef MODE_BLOOMBLUR\n"
844 "varying TexCoord;\n"
845 "#ifdef VERTEX_SHADER\n"
846 "void main(void)\n"
847 "{\n"
848 "       gl_FrontColor = gl_Color;\n"
849 "       TexCoord = gl_MultiTexCoord0.xy;\n"
850 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
851 "}\n"
852 "#endif\n"
853 "\n"
854 "#ifdef FRAGMENT_SHADER\n"
855 "uniform sampler2D Texture_First;\n"
856 "uniform vec4 BloomBlur_Parameters;\n"
857 "\n"
858 "void main(void)\n"
859 "{\n"
860 "       int i;\n"
861 "       vec2 tc = TexCoord;\n"
862 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
863 "       tc += BloomBlur_Parameters.xy;\n"
864 "       for (i = 1;i < SAMPLES;i++)\n"
865 "       {\n"
866 "               color += texture2D(Texture_First, tc).rgb;\n"
867 "               tc += BloomBlur_Parameters.xy;\n"
868 "       }\n"
869 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
870 "}\n"
871 "#endif\n"
872 "#else // !MODE_BLOOMBLUR\n"
873 "#ifdef MODE_REFRACTION\n"
874 "varying vec2 TexCoord;\n"
875 "varying vec4 ModelViewProjectionPosition;\n"
876 "uniform mat4 TexMatrix;\n"
877 "#ifdef VERTEX_SHADER\n"
878 "\n"
879 "void main(void)\n"
880 "{\n"
881 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
882 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
883 "       ModelViewProjectionPosition = gl_Position;\n"
884 "}\n"
885 "#endif\n"
886 "\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "uniform sampler2D Texture_Normal;\n"
889 "uniform sampler2D Texture_Refraction;\n"
890 "uniform sampler2D Texture_Reflection;\n"
891 "\n"
892 "uniform vec4 DistortScaleRefractReflect;\n"
893 "uniform vec4 ScreenScaleRefractReflect;\n"
894 "uniform vec4 ScreenCenterRefractReflect;\n"
895 "uniform vec4 RefractColor;\n"
896 "uniform vec4 ReflectColor;\n"
897 "uniform float ReflectFactor;\n"
898 "uniform float ReflectOffset;\n"
899 "\n"
900 "void main(void)\n"
901 "{\n"
902 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
903 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
904 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
905 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
906 "       // FIXME temporary hack to detect the case that the reflection\n"
907 "       // gets blackened at edges due to leaving the area that contains actual\n"
908 "       // content.\n"
909 "       // Remove this 'ack once we have a better way to stop this thing from\n"
910 "       // 'appening.\n"
911 "       float 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 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
915 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
916 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
917 "}\n"
918 "#endif\n"
919 "#else // !MODE_REFRACTION\n"
920 "\n"
921 "\n"
922 "\n"
923 "\n"
924 "#ifdef MODE_WATER\n"
925 "varying vec2 TexCoord;\n"
926 "varying vec3 EyeVector;\n"
927 "varying vec4 ModelViewProjectionPosition;\n"
928 "#ifdef VERTEX_SHADER\n"
929 "uniform vec3 EyePosition;\n"
930 "uniform mat4 TexMatrix;\n"
931 "\n"
932 "void main(void)\n"
933 "{\n"
934 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
935 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
936 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
937 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
938 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
939 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
940 "       ModelViewProjectionPosition = gl_Position;\n"
941 "}\n"
942 "#endif\n"
943 "\n"
944 "#ifdef FRAGMENT_SHADER\n"
945 "uniform sampler2D Texture_Normal;\n"
946 "uniform sampler2D Texture_Refraction;\n"
947 "uniform sampler2D Texture_Reflection;\n"
948 "\n"
949 "uniform vec4 DistortScaleRefractReflect;\n"
950 "uniform vec4 ScreenScaleRefractReflect;\n"
951 "uniform vec4 ScreenCenterRefractReflect;\n"
952 "uniform vec4 RefractColor;\n"
953 "uniform vec4 ReflectColor;\n"
954 "uniform float ReflectFactor;\n"
955 "uniform float ReflectOffset;\n"
956 "uniform float ClientTime;\n"
957 "#ifdef USENORMALMAPSCROLLBLEND\n"
958 "uniform vec2 NormalmapScrollBlend;\n"
959 "#endif\n"
960 "\n"
961 "void main(void)\n"
962 "{\n"
963 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
964 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
965 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
966 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
967 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
968 "       #ifdef USENORMALMAPSCROLLBLEND\n"
969 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
970 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
971 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
972 "       #else\n"
973 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
974 "       #endif\n"
975 "       // FIXME temporary hack to detect the case that the reflection\n"
976 "       // gets blackened at edges due to leaving the area that contains actual\n"
977 "       // content.\n"
978 "       // Remove this 'ack once we have a better way to stop this thing from\n"
979 "       // 'appening.\n"
980 "       float 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 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
984 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\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 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
989 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
990 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
991 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
992 "}\n"
993 "#endif\n"
994 "#else // !MODE_WATER\n"
995 "\n"
996 "\n"
997 "\n"
998 "\n"
999 "// common definitions between vertex shader and fragment shader:\n"
1000 "\n"
1001 "varying vec2 TexCoord;\n"
1002 "#ifdef USEVERTEXTEXTUREBLEND\n"
1003 "varying vec2 TexCoord2;\n"
1004 "#endif\n"
1005 "#ifdef USELIGHTMAP\n"
1006 "varying vec2 TexCoordLightmap;\n"
1007 "#endif\n"
1008 "\n"
1009 "#ifdef MODE_LIGHTSOURCE\n"
1010 "varying vec3 CubeVector;\n"
1011 "#endif\n"
1012 "\n"
1013 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1014 "varying vec3 LightVector;\n"
1015 "#endif\n"
1016 "\n"
1017 "#ifdef USEEYEVECTOR\n"
1018 "varying vec3 EyeVector;\n"
1019 "#endif\n"
1020 "#ifdef USEFOG\n"
1021 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1022 "#endif\n"
1023 "\n"
1024 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1025 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1026 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1027 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1028 "#endif\n"
1029 "\n"
1030 "#ifdef USEREFLECTION\n"
1031 "varying vec4 ModelViewProjectionPosition;\n"
1032 "#endif\n"
1033 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1034 "uniform vec3 LightPosition;\n"
1035 "varying vec4 ModelViewPosition;\n"
1036 "#endif\n"
1037 "\n"
1038 "#ifdef MODE_LIGHTSOURCE\n"
1039 "uniform vec3 LightPosition;\n"
1040 "#endif\n"
1041 "uniform vec3 EyePosition;\n"
1042 "#ifdef MODE_LIGHTDIRECTION\n"
1043 "uniform vec3 LightDir;\n"
1044 "#endif\n"
1045 "uniform vec4 FogPlane;\n"
1046 "\n"
1047 "#ifdef USESHADOWMAPORTHO\n"
1048 "varying vec3 ShadowMapTC;\n"
1049 "#endif\n"
1050 "\n"
1051 "\n"
1052 "\n"
1053 "\n"
1054 "\n"
1055 "// 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"
1056 "\n"
1057 "// fragment shader specific:\n"
1058 "#ifdef FRAGMENT_SHADER\n"
1059 "\n"
1060 "uniform sampler2D Texture_Normal;\n"
1061 "uniform sampler2D Texture_Color;\n"
1062 "uniform sampler2D Texture_Gloss;\n"
1063 "#ifdef USEGLOW\n"
1064 "uniform sampler2D Texture_Glow;\n"
1065 "#endif\n"
1066 "#ifdef USEVERTEXTEXTUREBLEND\n"
1067 "uniform sampler2D Texture_SecondaryNormal;\n"
1068 "uniform sampler2D Texture_SecondaryColor;\n"
1069 "uniform sampler2D Texture_SecondaryGloss;\n"
1070 "#ifdef USEGLOW\n"
1071 "uniform sampler2D Texture_SecondaryGlow;\n"
1072 "#endif\n"
1073 "#endif\n"
1074 "#ifdef USECOLORMAPPING\n"
1075 "uniform sampler2D Texture_Pants;\n"
1076 "uniform sampler2D Texture_Shirt;\n"
1077 "#endif\n"
1078 "#ifdef USEFOG\n"
1079 "#ifdef USEFOGHEIGHTTEXTURE\n"
1080 "uniform sampler2D Texture_FogHeightTexture;\n"
1081 "#endif\n"
1082 "uniform sampler2D Texture_FogMask;\n"
1083 "#endif\n"
1084 "#ifdef USELIGHTMAP\n"
1085 "uniform sampler2D Texture_Lightmap;\n"
1086 "#endif\n"
1087 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1088 "uniform sampler2D Texture_Deluxemap;\n"
1089 "#endif\n"
1090 "#ifdef USEREFLECTION\n"
1091 "uniform sampler2D Texture_Reflection;\n"
1092 "#endif\n"
1093 "\n"
1094 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1095 "uniform sampler2D Texture_ScreenDepth;\n"
1096 "uniform sampler2D Texture_ScreenNormalMap;\n"
1097 "#endif\n"
1098 "#ifdef USEDEFERREDLIGHTMAP\n"
1099 "uniform sampler2D Texture_ScreenDiffuse;\n"
1100 "uniform sampler2D Texture_ScreenSpecular;\n"
1101 "#endif\n"
1102 "\n"
1103 "uniform myhalf3 Color_Pants;\n"
1104 "uniform myhalf3 Color_Shirt;\n"
1105 "uniform myhalf3 FogColor;\n"
1106 "\n"
1107 "#ifdef USEFOG\n"
1108 "uniform float FogRangeRecip;\n"
1109 "uniform float FogPlaneViewDist;\n"
1110 "uniform float FogHeightFade;\n"
1111 "vec3 FogVertex(vec3 surfacecolor)\n"
1112 "{\n"
1113 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1114 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1115 "       float fogfrac;\n"
1116 "#ifdef USEFOGHEIGHTTEXTURE\n"
1117 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1118 "       fogfrac = fogheightpixel.a;\n"
1119 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1120 "#else\n"
1121 "# ifdef USEFOGOUTSIDE\n"
1122 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1123 "# else\n"
1124 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1125 "# endif\n"
1126 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1127 "#endif\n"
1128 "}\n"
1129 "#endif\n"
1130 "\n"
1131 "#ifdef USEOFFSETMAPPING\n"
1132 "uniform float OffsetMapping_Scale;\n"
1133 "vec2 OffsetMapping(vec2 TexCoord)\n"
1134 "{\n"
1135 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1136 "       // 14 sample relief mapping: linear search and then binary search\n"
1137 "       // this basically steps forward a small amount repeatedly until it finds\n"
1138 "       // itself inside solid, then jitters forward and back using decreasing\n"
1139 "       // amounts to find the impact\n"
1140 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1141 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1142 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1143 "       vec3 RT = vec3(TexCoord, 1);\n"
1144 "       OffsetVector *= 0.1;\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);\n"
1154 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1155 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1156 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1157 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1158 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1159 "       return RT.xy;\n"
1160 "#else\n"
1161 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1162 "       // this basically moves forward the full distance, and then backs up based\n"
1163 "       // on height of samples\n"
1164 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1165 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1166 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1167 "       TexCoord += OffsetVector;\n"
1168 "       OffsetVector *= 0.5;\n"
1169 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1170 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1171 "       return TexCoord;\n"
1172 "#endif\n"
1173 "}\n"
1174 "#endif // USEOFFSETMAPPING\n"
1175 "\n"
1176 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1177 "uniform sampler2D Texture_Attenuation;\n"
1178 "uniform samplerCube Texture_Cube;\n"
1179 "#endif\n"
1180 "\n"
1181 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1182 "\n"
1183 "#ifdef USESHADOWMAP2D\n"
1184 "# ifdef USESHADOWSAMPLER\n"
1185 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1186 "# else\n"
1187 "uniform sampler2D Texture_ShadowMap2D;\n"
1188 "# endif\n"
1189 "#endif\n"
1190 "\n"
1191 "#ifdef USESHADOWMAPVSDCT\n"
1192 "uniform samplerCube Texture_CubeProjection;\n"
1193 "#endif\n"
1194 "\n"
1195 "#if defined(USESHADOWMAP2D)\n"
1196 "uniform vec2 ShadowMap_TextureScale;\n"
1197 "uniform vec4 ShadowMap_Parameters;\n"
1198 "#endif\n"
1199 "\n"
1200 "#if defined(USESHADOWMAP2D)\n"
1201 "# ifdef USESHADOWMAPORTHO\n"
1202 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1203 "# else\n"
1204 "#  ifdef USESHADOWMAPVSDCT\n"
1205 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1206 "{\n"
1207 "       vec3 adir = abs(dir);\n"
1208 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1209 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1210 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1211 "}\n"
1212 "#  else\n"
1213 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1214 "{\n"
1215 "       vec3 adir = abs(dir);\n"
1216 "       float ma = adir.z;\n"
1217 "       vec4 proj = vec4(dir, 2.5);\n"
1218 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1219 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1220 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1221 "       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"
1222 "}\n"
1223 "#  endif\n"
1224 "# endif\n"
1225 "#endif // defined(USESHADOWMAP2D)\n"
1226 "\n"
1227 "# ifdef USESHADOWMAP2D\n"
1228 "float ShadowMapCompare(vec3 dir)\n"
1229 "{\n"
1230 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1231 "       float f;\n"
1232 "\n"
1233 "#  ifdef USESHADOWSAMPLER\n"
1234 "#    ifdef USESHADOWMAPPCF\n"
1235 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1236 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1237 "       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"
1238 "#    else\n"
1239 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1240 "#    endif\n"
1241 "#  else\n"
1242 "#    ifdef USESHADOWMAPPCF\n"
1243 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1244 "#      ifdef GL_ARB_texture_gather\n"
1245 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1246 "#      else\n"
1247 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1248 "#      endif\n"
1249 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1250 "#      if USESHADOWMAPPCF > 1\n"
1251 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1252 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1253 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1254 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1255 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1256 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1257 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1258 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1259 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1260 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1261 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1262 "       locols.yz += group2.ab;\n"
1263 "       hicols.yz += group8.rg;\n"
1264 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1265 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1266 "                               mix(locols, hicols, offset.y);\n"
1267 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1268 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1269 "       f = dot(cols, vec4(1.0/25.0));\n"
1270 "#      else\n"
1271 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1272 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1273 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1274 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1275 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1276 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1277 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1278 "#      endif\n"
1279 "#     else\n"
1280 "#      ifdef GL_EXT_gpu_shader4\n"
1281 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1282 "#      else\n"
1283 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1284 "#      endif\n"
1285 "#      if USESHADOWMAPPCF > 1\n"
1286 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1287 "       center *= ShadowMap_TextureScale;\n"
1288 "       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"
1289 "       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"
1290 "       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"
1291 "       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"
1292 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1293 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1294 "#      else\n"
1295 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1296 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1297 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1298 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1299 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1300 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1301 "#      endif\n"
1302 "#     endif\n"
1303 "#    else\n"
1304 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1305 "#    endif\n"
1306 "#  endif\n"
1307 "#  ifdef USESHADOWMAPORTHO\n"
1308 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1309 "#  else\n"
1310 "       return f;\n"
1311 "#  endif\n"
1312 "}\n"
1313 "# endif\n"
1314 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1315 "#endif // FRAGMENT_SHADER\n"
1316 "\n"
1317 "\n"
1318 "\n"
1319 "\n"
1320 "#ifdef MODE_DEFERREDGEOMETRY\n"
1321 "#ifdef VERTEX_SHADER\n"
1322 "uniform mat4 TexMatrix;\n"
1323 "#ifdef USEVERTEXTEXTUREBLEND\n"
1324 "uniform mat4 BackgroundTexMatrix;\n"
1325 "#endif\n"
1326 "uniform mat4 ModelViewMatrix;\n"
1327 "void main(void)\n"
1328 "{\n"
1329 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1330 "#ifdef USEVERTEXTEXTUREBLEND\n"
1331 "       gl_FrontColor = gl_Color;\n"
1332 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1333 "#endif\n"
1334 "\n"
1335 "       // transform unnormalized eye direction into tangent space\n"
1336 "#ifdef USEOFFSETMAPPING\n"
1337 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1338 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1339 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1340 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1341 "#endif\n"
1342 "\n"
1343 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1344 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1345 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1346 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1347 "}\n"
1348 "#endif // VERTEX_SHADER\n"
1349 "\n"
1350 "#ifdef FRAGMENT_SHADER\n"
1351 "void main(void)\n"
1352 "{\n"
1353 "#ifdef USEOFFSETMAPPING\n"
1354 "       // apply offsetmapping\n"
1355 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1356 "#define TexCoord TexCoordOffset\n"
1357 "#endif\n"
1358 "\n"
1359 "#ifdef USEALPHAKILL\n"
1360 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1361 "               discard;\n"
1362 "#endif\n"
1363 "\n"
1364 "#ifdef USEVERTEXTEXTUREBLEND\n"
1365 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1366 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1367 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1368 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1369 "#endif\n"
1370 "\n"
1371 "#ifdef USEVERTEXTEXTUREBLEND\n"
1372 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1373 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1374 "#else\n"
1375 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1376 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1377 "#endif\n"
1378 "\n"
1379 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1380 "}\n"
1381 "#endif // FRAGMENT_SHADER\n"
1382 "#else // !MODE_DEFERREDGEOMETRY\n"
1383 "\n"
1384 "\n"
1385 "\n"
1386 "\n"
1387 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1388 "#ifdef VERTEX_SHADER\n"
1389 "uniform mat4 ModelViewMatrix;\n"
1390 "void main(void)\n"
1391 "{\n"
1392 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1393 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1394 "}\n"
1395 "#endif // VERTEX_SHADER\n"
1396 "\n"
1397 "#ifdef FRAGMENT_SHADER\n"
1398 "uniform mat4 ViewToLight;\n"
1399 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1400 "uniform vec2 ScreenToDepth;\n"
1401 "uniform myhalf3 DeferredColor_Ambient;\n"
1402 "uniform myhalf3 DeferredColor_Diffuse;\n"
1403 "#ifdef USESPECULAR\n"
1404 "uniform myhalf3 DeferredColor_Specular;\n"
1405 "uniform myhalf SpecularPower;\n"
1406 "#endif\n"
1407 "uniform myhalf2 PixelToScreenTexCoord;\n"
1408 "void main(void)\n"
1409 "{\n"
1410 "       // calculate viewspace pixel position\n"
1411 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1412 "       vec3 position;\n"
1413 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1414 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1415 "       // decode viewspace pixel normal\n"
1416 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1417 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1418 "       // surfacenormal = pixel normal in viewspace\n"
1419 "       // LightVector = pixel to light in viewspace\n"
1420 "       // CubeVector = position in lightspace\n"
1421 "       // eyevector = pixel to view in viewspace\n"
1422 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1423 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1424 "#ifdef USEDIFFUSE\n"
1425 "       // calculate diffuse shading\n"
1426 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1427 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1428 "#endif\n"
1429 "#ifdef USESPECULAR\n"
1430 "       // calculate directional shading\n"
1431 "       vec3 eyevector = position * -1.0;\n"
1432 "#  ifdef USEEXACTSPECULARMATH\n"
1433 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1434 "#  else\n"
1435 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1436 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1437 "#  endif\n"
1438 "#endif\n"
1439 "\n"
1440 "#if defined(USESHADOWMAP2D)\n"
1441 "       fade *= ShadowMapCompare(CubeVector);\n"
1442 "#endif\n"
1443 "\n"
1444 "#ifdef USEDIFFUSE\n"
1445 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1446 "#else\n"
1447 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1448 "#endif\n"
1449 "#ifdef USESPECULAR\n"
1450 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1451 "#else\n"
1452 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1453 "#endif\n"
1454 "\n"
1455 "# ifdef USECUBEFILTER\n"
1456 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1457 "       gl_FragData[0].rgb *= cubecolor;\n"
1458 "       gl_FragData[1].rgb *= cubecolor;\n"
1459 "# endif\n"
1460 "}\n"
1461 "#endif // FRAGMENT_SHADER\n"
1462 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1463 "\n"
1464 "\n"
1465 "\n"
1466 "\n"
1467 "#ifdef VERTEX_SHADER\n"
1468 "uniform mat4 TexMatrix;\n"
1469 "#ifdef USEVERTEXTEXTUREBLEND\n"
1470 "uniform mat4 BackgroundTexMatrix;\n"
1471 "#endif\n"
1472 "#ifdef MODE_LIGHTSOURCE\n"
1473 "uniform mat4 ModelToLight;\n"
1474 "#endif\n"
1475 "#ifdef USESHADOWMAPORTHO\n"
1476 "uniform mat4 ShadowMapMatrix;\n"
1477 "#endif\n"
1478 "void main(void)\n"
1479 "{\n"
1480 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1481 "       gl_FrontColor = gl_Color;\n"
1482 "#endif\n"
1483 "       // copy the surface texcoord\n"
1484 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1485 "#ifdef USEVERTEXTEXTUREBLEND\n"
1486 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1487 "#endif\n"
1488 "#ifdef USELIGHTMAP\n"
1489 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1490 "#endif\n"
1491 "\n"
1492 "#ifdef MODE_LIGHTSOURCE\n"
1493 "       // transform vertex position into light attenuation/cubemap space\n"
1494 "       // (-1 to +1 across the light box)\n"
1495 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1496 "\n"
1497 "# ifdef USEDIFFUSE\n"
1498 "       // transform unnormalized light direction into tangent space\n"
1499 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1500 "       //  normalize it per pixel)\n"
1501 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1502 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1503 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1504 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1505 "# endif\n"
1506 "#endif\n"
1507 "\n"
1508 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1509 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1510 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1511 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1512 "#endif\n"
1513 "\n"
1514 "       // transform unnormalized eye direction into tangent space\n"
1515 "#ifdef USEEYEVECTOR\n"
1516 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1517 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1518 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1519 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1520 "#endif\n"
1521 "\n"
1522 "#ifdef USEFOG\n"
1523 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1524 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1525 "#endif\n"
1526 "\n"
1527 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1528 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1529 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1530 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1531 "#endif\n"
1532 "\n"
1533 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1534 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1535 "\n"
1536 "#ifdef USESHADOWMAPORTHO\n"
1537 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1538 "#endif\n"
1539 "\n"
1540 "#ifdef USEREFLECTION\n"
1541 "       ModelViewProjectionPosition = gl_Position;\n"
1542 "#endif\n"
1543 "}\n"
1544 "#endif // VERTEX_SHADER\n"
1545 "\n"
1546 "\n"
1547 "\n"
1548 "\n"
1549 "#ifdef FRAGMENT_SHADER\n"
1550 "#ifdef USEDEFERREDLIGHTMAP\n"
1551 "uniform myhalf2 PixelToScreenTexCoord;\n"
1552 "uniform myhalf3 DeferredMod_Diffuse;\n"
1553 "uniform myhalf3 DeferredMod_Specular;\n"
1554 "#endif\n"
1555 "uniform myhalf3 Color_Ambient;\n"
1556 "uniform myhalf3 Color_Diffuse;\n"
1557 "uniform myhalf3 Color_Specular;\n"
1558 "uniform myhalf SpecularPower;\n"
1559 "#ifdef USEGLOW\n"
1560 "uniform myhalf3 Color_Glow;\n"
1561 "#endif\n"
1562 "uniform myhalf Alpha;\n"
1563 "#ifdef USEREFLECTION\n"
1564 "uniform vec4 DistortScaleRefractReflect;\n"
1565 "uniform vec4 ScreenScaleRefractReflect;\n"
1566 "uniform vec4 ScreenCenterRefractReflect;\n"
1567 "uniform myhalf4 ReflectColor;\n"
1568 "#endif\n"
1569 "#ifdef USEREFLECTCUBE\n"
1570 "uniform mat4 ModelToReflectCube;\n"
1571 "uniform sampler2D Texture_ReflectMask;\n"
1572 "uniform samplerCube Texture_ReflectCube;\n"
1573 "#endif\n"
1574 "#ifdef MODE_LIGHTDIRECTION\n"
1575 "uniform myhalf3 LightColor;\n"
1576 "#endif\n"
1577 "#ifdef MODE_LIGHTSOURCE\n"
1578 "uniform myhalf3 LightColor;\n"
1579 "#endif\n"
1580 "void main(void)\n"
1581 "{\n"
1582 "#ifdef USEOFFSETMAPPING\n"
1583 "       // apply offsetmapping\n"
1584 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1585 "#define TexCoord TexCoordOffset\n"
1586 "#endif\n"
1587 "\n"
1588 "       // combine the diffuse textures (base, pants, shirt)\n"
1589 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1590 "#ifdef USEALPHAKILL\n"
1591 "       if (color.a < 0.5)\n"
1592 "               discard;\n"
1593 "#endif\n"
1594 "       color.a *= Alpha;\n"
1595 "#ifdef USECOLORMAPPING\n"
1596 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1597 "#endif\n"
1598 "#ifdef USEVERTEXTEXTUREBLEND\n"
1599 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1600 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1601 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1602 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1603 "       color.a = 1.0;\n"
1604 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1605 "#endif\n"
1606 "\n"
1607 "       // get the surface normal\n"
1608 "#ifdef USEVERTEXTEXTUREBLEND\n"
1609 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1610 "#else\n"
1611 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1612 "#endif\n"
1613 "\n"
1614 "       // get the material colors\n"
1615 "       myhalf3 diffusetex = color.rgb;\n"
1616 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1617 "# ifdef USEVERTEXTEXTUREBLEND\n"
1618 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1619 "# else\n"
1620 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1621 "# endif\n"
1622 "#endif\n"
1623 "\n"
1624 "#ifdef USEREFLECTCUBE\n"
1625 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1626 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1627 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1628 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1629 "#endif\n"
1630 "\n"
1631 "\n"
1632 "\n"
1633 "\n"
1634 "#ifdef MODE_LIGHTSOURCE\n"
1635 "       // light source\n"
1636 "#ifdef USEDIFFUSE\n"
1637 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1638 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1639 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1640 "#ifdef USESPECULAR\n"
1641 "#ifdef USEEXACTSPECULARMATH\n"
1642 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1643 "#else\n"
1644 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1645 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1646 "#endif\n"
1647 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1648 "#endif\n"
1649 "#else\n"
1650 "       color.rgb = diffusetex * Color_Ambient;\n"
1651 "#endif\n"
1652 "       color.rgb *= LightColor;\n"
1653 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1654 "#if defined(USESHADOWMAP2D)\n"
1655 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1656 "#endif\n"
1657 "# ifdef USECUBEFILTER\n"
1658 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1659 "# endif\n"
1660 "#endif // MODE_LIGHTSOURCE\n"
1661 "\n"
1662 "\n"
1663 "\n"
1664 "\n"
1665 "#ifdef MODE_LIGHTDIRECTION\n"
1666 "#define SHADING\n"
1667 "#ifdef USEDIFFUSE\n"
1668 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1669 "#endif\n"
1670 "#define lightcolor LightColor\n"
1671 "#endif // MODE_LIGHTDIRECTION\n"
1672 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1673 "#define SHADING\n"
1674 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1675 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1676 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1677 "       // convert modelspace light vector to tangentspace\n"
1678 "       myhalf3 lightnormal;\n"
1679 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1680 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1681 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1682 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1683 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1684 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1685 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1686 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1687 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1688 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1689 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1690 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1691 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1692 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1693 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1694 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1695 "#define SHADING\n"
1696 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1697 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1698 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1699 "#endif\n"
1700 "\n"
1701 "\n"
1702 "\n"
1703 "\n"
1704 "#ifdef MODE_FAKELIGHT\n"
1705 "#define SHADING\n"
1706 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1707 "myhalf3 lightcolor = myhalf3(1.0);\n"
1708 "#endif // MODE_FAKELIGHT\n"
1709 "\n"
1710 "\n"
1711 "\n"
1712 "\n"
1713 "#ifdef MODE_LIGHTMAP\n"
1714 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1715 "#endif // MODE_LIGHTMAP\n"
1716 "#ifdef MODE_VERTEXCOLOR\n"
1717 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1718 "#endif // MODE_VERTEXCOLOR\n"
1719 "#ifdef MODE_FLATCOLOR\n"
1720 "       color.rgb = diffusetex * Color_Ambient;\n"
1721 "#endif // MODE_FLATCOLOR\n"
1722 "\n"
1723 "\n"
1724 "\n"
1725 "\n"
1726 "#ifdef SHADING\n"
1727 "# ifdef USEDIFFUSE\n"
1728 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1729 "#  ifdef USESPECULAR\n"
1730 "#   ifdef USEEXACTSPECULARMATH\n"
1731 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1732 "#   else\n"
1733 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1734 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1735 "#   endif\n"
1736 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1737 "#  else\n"
1738 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1739 "#  endif\n"
1740 "# else\n"
1741 "       color.rgb = diffusetex * Color_Ambient;\n"
1742 "# endif\n"
1743 "#endif\n"
1744 "\n"
1745 "#ifdef USESHADOWMAPORTHO\n"
1746 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1747 "#endif\n"
1748 "\n"
1749 "#ifdef USEDEFERREDLIGHTMAP\n"
1750 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1751 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1752 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1753 "#endif\n"
1754 "\n"
1755 "#ifdef USEGLOW\n"
1756 "#ifdef USEVERTEXTEXTUREBLEND\n"
1757 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1758 "#else\n"
1759 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1760 "#endif\n"
1761 "#endif\n"
1762 "\n"
1763 "#ifdef USEFOG\n"
1764 "       color.rgb = FogVertex(color.rgb);\n"
1765 "#endif\n"
1766 "\n"
1767 "       // 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"
1768 "#ifdef USEREFLECTION\n"
1769 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1770 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1771 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1772 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1773 "       // FIXME temporary hack to detect the case that the reflection\n"
1774 "       // gets blackened at edges due to leaving the area that contains actual\n"
1775 "       // content.\n"
1776 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1777 "       // 'appening.\n"
1778 "       float 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 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1782 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1783 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1784 "#endif\n"
1785 "\n"
1786 "       gl_FragColor = vec4(color);\n"
1787 "}\n"
1788 "#endif // FRAGMENT_SHADER\n"
1789 "\n"
1790 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1791 "#endif // !MODE_DEFERREDGEOMETRY\n"
1792 "#endif // !MODE_WATER\n"
1793 "#endif // !MODE_REFRACTION\n"
1794 "#endif // !MODE_BLOOMBLUR\n"
1795 "#endif // !MODE_GENERIC\n"
1796 "#endif // !MODE_POSTPROCESS\n"
1797 "#endif // !MODE_SHOWDEPTH\n"
1798 "#endif // !MODE_DEPTH_OR_SHADOW\n"
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
1829 const char *builtincgshaderstring =
1830 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1831 "// written by Forest 'LordHavoc' Hale\n"
1832 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1833 "\n"
1834 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1835 "#if defined(USEREFLECTION)\n"
1836 "#undef USESHADOWMAPORTHO\n"
1837 "#endif\n"
1838 "\n"
1839 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1840 "# define USEFOG\n"
1841 "#endif\n"
1842 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1843 "#define USELIGHTMAP\n"
1844 "#endif\n"
1845 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1846 "#define USEEYEVECTOR\n"
1847 "#endif\n"
1848 "\n"
1849 "#ifdef FRAGMENT_SHADER\n"
1850 "#ifdef HLSL\n"
1851 "//#undef USESHADOWMAPPCF\n"
1852 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1853 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1854 "#else\n"
1855 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1856 "#endif\n"
1857 "#endif\n"
1858 "\n"
1859 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1860 "#ifdef VERTEX_SHADER\n"
1861 "void main\n"
1862 "(\n"
1863 "float4 gl_Vertex : POSITION,\n"
1864 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1865 "out float4 gl_Position : POSITION,\n"
1866 "out float Depth : TEXCOORD0\n"
1867 ")\n"
1868 "{\n"
1869 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1870 "       Depth = gl_Position.z;\n"
1871 "}\n"
1872 "#endif\n"
1873 "\n"
1874 "#ifdef FRAGMENT_SHADER\n"
1875 "void main\n"
1876 "(\n"
1877 "float Depth : TEXCOORD0,\n"
1878 "out float4 gl_FragColor : COLOR\n"
1879 ")\n"
1880 "{\n"
1881 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1882 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1883 "       temp.yz -= floor(temp.yz);\n"
1884 "       gl_FragColor = temp;\n"
1885 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1886 "}\n"
1887 "#endif\n"
1888 "#else // !MODE_DEPTH_ORSHADOW\n"
1889 "\n"
1890 "\n"
1891 "\n"
1892 "\n"
1893 "#ifdef MODE_SHOWDEPTH\n"
1894 "#ifdef VERTEX_SHADER\n"
1895 "void main\n"
1896 "(\n"
1897 "float4 gl_Vertex : POSITION,\n"
1898 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1899 "out float4 gl_Position : POSITION,\n"
1900 "out float4 gl_FrontColor : COLOR0\n"
1901 ")\n"
1902 "{\n"
1903 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1904 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1905 "}\n"
1906 "#endif\n"
1907 "\n"
1908 "#ifdef FRAGMENT_SHADER\n"
1909 "void main\n"
1910 "(\n"
1911 "float4 gl_FrontColor : COLOR0,\n"
1912 "out float4 gl_FragColor : COLOR\n"
1913 ")\n"
1914 "{\n"
1915 "       gl_FragColor = gl_FrontColor;\n"
1916 "}\n"
1917 "#endif\n"
1918 "#else // !MODE_SHOWDEPTH\n"
1919 "\n"
1920 "\n"
1921 "\n"
1922 "\n"
1923 "#ifdef MODE_POSTPROCESS\n"
1924 "\n"
1925 "#ifdef VERTEX_SHADER\n"
1926 "void main\n"
1927 "(\n"
1928 "float4 gl_Vertex : POSITION,\n"
1929 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1930 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1931 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1932 "out float4 gl_Position : POSITION,\n"
1933 "out float2 TexCoord1 : TEXCOORD0,\n"
1934 "out float2 TexCoord2 : TEXCOORD1\n"
1935 ")\n"
1936 "{\n"
1937 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1938 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1939 "#ifdef USEBLOOM\n"
1940 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1941 "#endif\n"
1942 "}\n"
1943 "#endif\n"
1944 "\n"
1945 "#ifdef FRAGMENT_SHADER\n"
1946 "void main\n"
1947 "(\n"
1948 "float2 TexCoord1 : TEXCOORD0,\n"
1949 "float2 TexCoord2 : TEXCOORD1,\n"
1950 "uniform sampler Texture_First : register(s0),\n"
1951 "#ifdef USEBLOOM\n"
1952 "uniform sampler Texture_Second : register(s1),\n"
1953 "#endif\n"
1954 "#ifdef USEGAMMARAMPS\n"
1955 "uniform sampler Texture_GammaRamps : register(s2),\n"
1956 "#endif\n"
1957 "#ifdef USESATURATION\n"
1958 "uniform float Saturation : register(c30),\n"
1959 "#endif\n"
1960 "#ifdef USEVIEWTINT\n"
1961 "uniform float4 ViewTintColor : register(c41),\n"
1962 "#endif\n"
1963 "uniform float4 UserVec1 : register(c37),\n"
1964 "uniform float4 UserVec2 : register(c38),\n"
1965 "uniform float4 UserVec3 : register(c39),\n"
1966 "uniform float4 UserVec4 : register(c40),\n"
1967 "uniform float ClientTime : register(c2),\n"
1968 "uniform float2 PixelSize : register(c25),\n"
1969 "uniform float4 BloomColorSubtract : register(c43),\n"
1970 "out float4 gl_FragColor : COLOR\n"
1971 ")\n"
1972 "{\n"
1973 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1974 "#ifdef USEBLOOM\n"
1975 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1976 "#endif\n"
1977 "#ifdef USEVIEWTINT\n"
1978 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1979 "#endif\n"
1980 "\n"
1981 "#ifdef USEPOSTPROCESSING\n"
1982 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1983 "// 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"
1984 "       float sobel = 1.0;\n"
1985 "       // float2 ts = textureSize(Texture_First, 0);\n"
1986 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1987 "       float2 px = PixelSize;\n"
1988 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1989 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1990 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1991 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1992 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1993 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1994 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1995 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1996 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1997 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1998 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1999 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2000 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2001 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2002 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2003 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2004 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2005 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2006 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2007 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2008 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2009 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2010 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2011 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2012 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2013 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2014 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2015 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2016 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2017 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2018 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2019 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2020 "#endif\n"
2021 "\n"
2022 "#ifdef USESATURATION\n"
2023 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2024 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2025 "       // 'vampire sight' effect, wheres red is compensated\n"
2026 "       #ifdef SATURATION_REDCOMPENSATE\n"
2027 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2028 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2029 "               gl_FragColor.r += r;\n"
2030 "       #else\n"
2031 "               // normal desaturation\n"
2032 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2033 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2034 "       #endif\n"
2035 "#endif\n"
2036 "\n"
2037 "#ifdef USEGAMMARAMPS\n"
2038 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2039 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2040 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2041 "#endif\n"
2042 "}\n"
2043 "#endif\n"
2044 "#else // !MODE_POSTPROCESS\n"
2045 "\n"
2046 "\n"
2047 "\n"
2048 "\n"
2049 "#ifdef MODE_GENERIC\n"
2050 "#ifdef VERTEX_SHADER\n"
2051 "void main\n"
2052 "(\n"
2053 "float4 gl_Vertex : POSITION,\n"
2054 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2055 "float4 gl_Color : COLOR0,\n"
2056 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2057 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2058 "out float4 gl_Position : POSITION,\n"
2059 "#ifdef USEDIFFUSE\n"
2060 "out float2 TexCoord1 : TEXCOORD0,\n"
2061 "#endif\n"
2062 "#ifdef USESPECULAR\n"
2063 "out float2 TexCoord2 : TEXCOORD1,\n"
2064 "#endif\n"
2065 "out float4 gl_FrontColor : COLOR\n"
2066 ")\n"
2067 "{\n"
2068 "#ifdef HLSL\n"
2069 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2070 "#else\n"
2071 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2072 "#endif\n"
2073 "#ifdef USEDIFFUSE\n"
2074 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2075 "#endif\n"
2076 "#ifdef USESPECULAR\n"
2077 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2078 "#endif\n"
2079 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2080 "}\n"
2081 "#endif\n"
2082 "\n"
2083 "#ifdef FRAGMENT_SHADER\n"
2084 "\n"
2085 "void main\n"
2086 "(\n"
2087 "float4 gl_FrontColor : COLOR0,\n"
2088 "float2 TexCoord1 : TEXCOORD0,\n"
2089 "float2 TexCoord2 : TEXCOORD1,\n"
2090 "#ifdef USEDIFFUSE\n"
2091 "uniform sampler Texture_First : register(s0),\n"
2092 "#endif\n"
2093 "#ifdef USESPECULAR\n"
2094 "uniform sampler Texture_Second : register(s1),\n"
2095 "#endif\n"
2096 "out float4 gl_FragColor : COLOR\n"
2097 ")\n"
2098 "{\n"
2099 "#ifdef USEVIEWTINT\n"
2100 "       gl_FragColor = gl_FrontColor;\n"
2101 "#else\n"
2102 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2103 "#endif\n"
2104 "#ifdef USEDIFFUSE\n"
2105 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2106 "#endif\n"
2107 "\n"
2108 "#ifdef USESPECULAR\n"
2109 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2110 "# ifdef USECOLORMAPPING\n"
2111 "       gl_FragColor *= tex2;\n"
2112 "# endif\n"
2113 "# ifdef USEGLOW\n"
2114 "       gl_FragColor += tex2;\n"
2115 "# endif\n"
2116 "# ifdef USEVERTEXTEXTUREBLEND\n"
2117 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2118 "# endif\n"
2119 "#endif\n"
2120 "}\n"
2121 "#endif\n"
2122 "#else // !MODE_GENERIC\n"
2123 "\n"
2124 "\n"
2125 "\n"
2126 "\n"
2127 "#ifdef MODE_BLOOMBLUR\n"
2128 "#ifdef VERTEX_SHADER\n"
2129 "void main\n"
2130 "(\n"
2131 "float4 gl_Vertex : POSITION,\n"
2132 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2133 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2134 "out float4 gl_Position : POSITION,\n"
2135 "out float2 TexCoord : TEXCOORD0\n"
2136 ")\n"
2137 "{\n"
2138 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2139 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2140 "}\n"
2141 "#endif\n"
2142 "\n"
2143 "#ifdef FRAGMENT_SHADER\n"
2144 "\n"
2145 "void main\n"
2146 "(\n"
2147 "float2 TexCoord : TEXCOORD0,\n"
2148 "uniform sampler Texture_First : register(s0),\n"
2149 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2150 "out float4 gl_FragColor : COLOR\n"
2151 ")\n"
2152 "{\n"
2153 "       int i;\n"
2154 "       float2 tc = TexCoord;\n"
2155 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2156 "       tc += BloomBlur_Parameters.xy;\n"
2157 "       for (i = 1;i < SAMPLES;i++)\n"
2158 "       {\n"
2159 "               color += tex2D(Texture_First, tc).rgb;\n"
2160 "               tc += BloomBlur_Parameters.xy;\n"
2161 "       }\n"
2162 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2163 "}\n"
2164 "#endif\n"
2165 "#else // !MODE_BLOOMBLUR\n"
2166 "#ifdef MODE_REFRACTION\n"
2167 "#ifdef VERTEX_SHADER\n"
2168 "void main\n"
2169 "(\n"
2170 "float4 gl_Vertex : POSITION,\n"
2171 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2172 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2173 "uniform float4x4 TexMatrix : register(c0),\n"
2174 "uniform float3 EyePosition : register(c24),\n"
2175 "out float4 gl_Position : POSITION,\n"
2176 "out float2 TexCoord : TEXCOORD0,\n"
2177 "out float3 EyeVector : TEXCOORD1,\n"
2178 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2179 ")\n"
2180 "{\n"
2181 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2182 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2183 "       ModelViewProjectionPosition = gl_Position;\n"
2184 "}\n"
2185 "#endif\n"
2186 "\n"
2187 "#ifdef FRAGMENT_SHADER\n"
2188 "void main\n"
2189 "(\n"
2190 "float2 TexCoord : TEXCOORD0,\n"
2191 "float3 EyeVector : TEXCOORD1,\n"
2192 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2193 "uniform sampler Texture_Normal : register(s0),\n"
2194 "uniform sampler Texture_Refraction : register(s3),\n"
2195 "uniform sampler Texture_Reflection : register(s7),\n"
2196 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2197 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2198 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2199 "uniform float4 RefractColor : register(c29),\n"
2200 "out float4 gl_FragColor : COLOR\n"
2201 ")\n"
2202 "{\n"
2203 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2204 "       //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"
2205 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2206 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2207 "       // FIXME temporary hack to detect the case that the reflection\n"
2208 "       // gets blackened at edges due to leaving the area that contains actual\n"
2209 "       // content.\n"
2210 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2211 "       // 'appening.\n"
2212 "       float 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 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2216 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2217 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2218 "}\n"
2219 "#endif\n"
2220 "#else // !MODE_REFRACTION\n"
2221 "\n"
2222 "\n"
2223 "\n"
2224 "\n"
2225 "#ifdef MODE_WATER\n"
2226 "#ifdef VERTEX_SHADER\n"
2227 "\n"
2228 "void main\n"
2229 "(\n"
2230 "float4 gl_Vertex : POSITION,\n"
2231 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2232 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2233 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2234 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2235 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2236 "uniform float4x4 TexMatrix : register(c0),\n"
2237 "uniform float3 EyePosition : register(c24),\n"
2238 "out float4 gl_Position : POSITION,\n"
2239 "out float2 TexCoord : TEXCOORD0,\n"
2240 "out float3 EyeVector : TEXCOORD1,\n"
2241 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2242 ")\n"
2243 "{\n"
2244 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2245 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2246 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2247 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2248 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2249 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2250 "       ModelViewProjectionPosition = gl_Position;\n"
2251 "}\n"
2252 "#endif\n"
2253 "\n"
2254 "#ifdef FRAGMENT_SHADER\n"
2255 "void main\n"
2256 "(\n"
2257 "float2 TexCoord : TEXCOORD0,\n"
2258 "float3 EyeVector : TEXCOORD1,\n"
2259 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2260 "uniform sampler Texture_Normal : register(s0),\n"
2261 "uniform sampler Texture_Refraction : register(s3),\n"
2262 "uniform sampler Texture_Reflection : register(s7),\n"
2263 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2264 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2265 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2266 "uniform float4 RefractColor : register(c29),\n"
2267 "uniform float4 ReflectColor : register(c26),\n"
2268 "uniform float ReflectFactor : register(c27),\n"
2269 "uniform float ReflectOffset : register(c28),\n"
2270 "out float4 gl_FragColor : COLOR\n"
2271 ")\n"
2272 "{\n"
2273 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2274 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2275 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2276 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2277 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2278 "       // FIXME temporary hack to detect the case that the reflection\n"
2279 "       // gets blackened at edges due to leaving the area that contains actual\n"
2280 "       // content.\n"
2281 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2282 "       // 'appening.\n"
2283 "       float 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 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2287 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\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 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2292 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2293 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2294 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2295 "}\n"
2296 "#endif\n"
2297 "#else // !MODE_WATER\n"
2298 "\n"
2299 "\n"
2300 "\n"
2301 "\n"
2302 "// 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"
2303 "\n"
2304 "// fragment shader specific:\n"
2305 "#ifdef FRAGMENT_SHADER\n"
2306 "\n"
2307 "#ifdef USEFOG\n"
2308 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2309 "{\n"
2310 "       float fogfrac;\n"
2311 "#ifdef USEFOGHEIGHTTEXTURE\n"
2312 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2313 "       fogfrac = fogheightpixel.a;\n"
2314 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2315 "#else\n"
2316 "# ifdef USEFOGOUTSIDE\n"
2317 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2318 "# else\n"
2319 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2320 "# endif\n"
2321 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2322 "#endif\n"
2323 "}\n"
2324 "#endif\n"
2325 "\n"
2326 "#ifdef USEOFFSETMAPPING\n"
2327 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2328 "{\n"
2329 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2330 "       // 14 sample relief mapping: linear search and then binary search\n"
2331 "       // this basically steps forward a small amount repeatedly until it finds\n"
2332 "       // itself inside solid, then jitters forward and back using decreasing\n"
2333 "       // amounts to find the impact\n"
2334 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2335 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2336 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2337 "       float3 RT = float3(TexCoord, 1);\n"
2338 "       OffsetVector *= 0.1;\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);\n"
2348 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2349 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2350 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2351 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2352 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2353 "       return RT.xy;\n"
2354 "#else\n"
2355 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2356 "       // this basically moves forward the full distance, and then backs up based\n"
2357 "       // on height of samples\n"
2358 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2359 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2360 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2361 "       TexCoord += OffsetVector;\n"
2362 "       OffsetVector *= 0.333;\n"
2363 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2364 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2365 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2366 "       return TexCoord;\n"
2367 "#endif\n"
2368 "}\n"
2369 "#endif // USEOFFSETMAPPING\n"
2370 "\n"
2371 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2372 "#if defined(USESHADOWMAP2D)\n"
2373 "# ifdef USESHADOWMAPORTHO\n"
2374 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2375 "# else\n"
2376 "#  ifdef USESHADOWMAPVSDCT\n"
2377 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2378 "{\n"
2379 "       float3 adir = abs(dir);\n"
2380 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2381 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2382 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2383 "}\n"
2384 "#  else\n"
2385 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2386 "{\n"
2387 "       float3 adir = abs(dir);\n"
2388 "       float ma = adir.z;\n"
2389 "       float4 proj = float4(dir, 2.5);\n"
2390 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2391 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2392 "#ifdef HLSL\n"
2393 "       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"
2394 "#else\n"
2395 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2396 "       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"
2397 "#endif\n"
2398 "}\n"
2399 "#  endif\n"
2400 "# endif\n"
2401 "#endif // defined(USESHADOWMAP2D)\n"
2402 "\n"
2403 "# ifdef USESHADOWMAP2D\n"
2404 "#ifdef USESHADOWMAPVSDCT\n"
2405 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2406 "#else\n"
2407 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2408 "#endif\n"
2409 "{\n"
2410 "#ifdef USESHADOWMAPVSDCT\n"
2411 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2412 "#else\n"
2413 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2414 "#endif\n"
2415 "       float f;\n"
2416 "\n"
2417 "#  ifdef USESHADOWSAMPLER\n"
2418 "#    ifdef USESHADOWMAPPCF\n"
2419 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2420 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2421 "       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"
2422 "#    else\n"
2423 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2424 "#    endif\n"
2425 "#  else\n"
2426 "#    ifdef USESHADOWMAPPCF\n"
2427 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2428 "#      ifdef GL_ARB_texture_gather\n"
2429 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2430 "#      else\n"
2431 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2432 "#      endif\n"
2433 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2434 "#      if USESHADOWMAPPCF > 1\n"
2435 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2436 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2437 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2438 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2439 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2440 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2441 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2442 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2443 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2444 "       float4 locols = float4(group1.ab, group3.ab);\n"
2445 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2446 "       locols.yz += group2.ab;\n"
2447 "       hicols.yz += group8.rg;\n"
2448 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2449 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2450 "                               lerp(locols, hicols, offset.y);\n"
2451 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2452 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2453 "       f = dot(cols, float4(1.0/25.0));\n"
2454 "#      else\n"
2455 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2456 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2457 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2458 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2459 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2460 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2461 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2462 "#      endif\n"
2463 "#     else\n"
2464 "#      ifdef GL_EXT_gpu_shader4\n"
2465 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2466 "#      else\n"
2467 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2468 "#      endif\n"
2469 "#      if USESHADOWMAPPCF > 1\n"
2470 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2471 "       center *= ShadowMap_TextureScale;\n"
2472 "       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"
2473 "       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"
2474 "       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"
2475 "       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"
2476 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2477 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2478 "#      else\n"
2479 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2480 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2481 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2482 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2483 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2484 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2485 "#      endif\n"
2486 "#     endif\n"
2487 "#    else\n"
2488 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2489 "#    endif\n"
2490 "#  endif\n"
2491 "#  ifdef USESHADOWMAPORTHO\n"
2492 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2493 "#  else\n"
2494 "       return f;\n"
2495 "#  endif\n"
2496 "}\n"
2497 "# endif\n"
2498 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2499 "#endif // FRAGMENT_SHADER\n"
2500 "\n"
2501 "\n"
2502 "\n"
2503 "\n"
2504 "#ifdef MODE_DEFERREDGEOMETRY\n"
2505 "#ifdef VERTEX_SHADER\n"
2506 "void main\n"
2507 "(\n"
2508 "float4 gl_Vertex : POSITION,\n"
2509 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2510 "#ifdef USEVERTEXTEXTUREBLEND\n"
2511 "float4 gl_Color : COLOR0,\n"
2512 "#endif\n"
2513 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2514 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2515 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2516 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2517 "uniform float4x4 TexMatrix : register(c0),\n"
2518 "#ifdef USEVERTEXTEXTUREBLEND\n"
2519 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2520 "#endif\n"
2521 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2522 "#ifdef USEOFFSETMAPPING\n"
2523 "uniform float3 EyePosition : register(c24),\n"
2524 "#endif\n"
2525 "out float4 gl_Position : POSITION,\n"
2526 "#ifdef USEVERTEXTEXTUREBLEND\n"
2527 "out float4 gl_FrontColor : COLOR,\n"
2528 "#endif\n"
2529 "out float4 TexCoordBoth : TEXCOORD0,\n"
2530 "#ifdef USEOFFSETMAPPING\n"
2531 "out float3 EyeVector : TEXCOORD2,\n"
2532 "#endif\n"
2533 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2534 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2535 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2536 ")\n"
2537 "{\n"
2538 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2539 "#ifdef USEVERTEXTEXTUREBLEND\n"
2540 "#ifdef HLSL\n"
2541 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2542 "#else\n"
2543 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2544 "#endif\n"
2545 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2546 "#endif\n"
2547 "\n"
2548 "       // transform unnormalized eye direction into tangent space\n"
2549 "#ifdef USEOFFSETMAPPING\n"
2550 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2551 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2552 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2553 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2554 "#endif\n"
2555 "\n"
2556 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2557 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2558 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2559 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2560 "       VectorR.w = gl_Position.z;\n"
2561 "}\n"
2562 "#endif // VERTEX_SHADER\n"
2563 "\n"
2564 "#ifdef FRAGMENT_SHADER\n"
2565 "void main\n"
2566 "(\n"
2567 "float4 TexCoordBoth : TEXCOORD0,\n"
2568 "float3 EyeVector : TEXCOORD2,\n"
2569 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2570 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2571 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2572 "uniform sampler Texture_Normal : register(s0),\n"
2573 "#ifdef USEALPHAKILL\n"
2574 "uniform sampler Texture_Color : register(s1),\n"
2575 "#endif\n"
2576 "uniform sampler Texture_Gloss : register(s2),\n"
2577 "#ifdef USEVERTEXTEXTUREBLEND\n"
2578 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2579 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2580 "#endif\n"
2581 "#ifdef USEOFFSETMAPPING\n"
2582 "uniform float OffsetMapping_Scale : register(c24),\n"
2583 "#endif\n"
2584 "uniform half SpecularPower : register(c36),\n"
2585 "#ifdef HLSL\n"
2586 "out float4 gl_FragData0 : COLOR0,\n"
2587 "out float4 gl_FragData1 : COLOR1\n"
2588 "#else\n"
2589 "out float4 gl_FragColor : COLOR\n"
2590 "#endif\n"
2591 ")\n"
2592 "{\n"
2593 "       float2 TexCoord = TexCoordBoth.xy;\n"
2594 "#ifdef USEOFFSETMAPPING\n"
2595 "       // apply offsetmapping\n"
2596 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2597 "#define TexCoord TexCoordOffset\n"
2598 "#endif\n"
2599 "\n"
2600 "#ifdef USEALPHAKILL\n"
2601 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2602 "               discard;\n"
2603 "#endif\n"
2604 "\n"
2605 "#ifdef USEVERTEXTEXTUREBLEND\n"
2606 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2607 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2608 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2609 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2610 "#endif\n"
2611 "\n"
2612 "#ifdef USEVERTEXTEXTUREBLEND\n"
2613 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2614 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2615 "#else\n"
2616 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2617 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2618 "#endif\n"
2619 "\n"
2620 "#ifdef HLSL\n"
2621 "       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"
2622 "       float Depth = VectorR.w / 256.0;\n"
2623 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2624 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2625 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2626 "       gl_FragData1 = depthcolor;\n"
2627 "#else\n"
2628 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2629 "#endif\n"
2630 "}\n"
2631 "#endif // FRAGMENT_SHADER\n"
2632 "#else // !MODE_DEFERREDGEOMETRY\n"
2633 "\n"
2634 "\n"
2635 "\n"
2636 "\n"
2637 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2638 "#ifdef VERTEX_SHADER\n"
2639 "void main\n"
2640 "(\n"
2641 "float4 gl_Vertex : POSITION,\n"
2642 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2643 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2644 "out float4 gl_Position : POSITION,\n"
2645 "out float4 ModelViewPosition : TEXCOORD0\n"
2646 ")\n"
2647 "{\n"
2648 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2649 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2650 "}\n"
2651 "#endif // VERTEX_SHADER\n"
2652 "\n"
2653 "#ifdef FRAGMENT_SHADER\n"
2654 "void main\n"
2655 "(\n"
2656 "#ifdef HLSL\n"
2657 "float2 Pixel : VPOS,\n"
2658 "#else\n"
2659 "float2 Pixel : WPOS,\n"
2660 "#endif\n"
2661 "float4 ModelViewPosition : TEXCOORD0,\n"
2662 "uniform float4x4 ViewToLight : register(c44),\n"
2663 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2664 "uniform float3 LightPosition : register(c23),\n"
2665 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2666 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2667 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2668 "#ifdef USESPECULAR\n"
2669 "uniform half3 DeferredColor_Specular : register(c11),\n"
2670 "uniform half SpecularPower : register(c36),\n"
2671 "#endif\n"
2672 "uniform sampler Texture_Attenuation : register(s9),\n"
2673 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2674 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2675 "\n"
2676 "#ifdef USECUBEFILTER\n"
2677 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2678 "#endif\n"
2679 "\n"
2680 "#ifdef USESHADOWMAP2D\n"
2681 "# ifdef USESHADOWSAMPLER\n"
2682 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2683 "# else\n"
2684 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2685 "# endif\n"
2686 "#endif\n"
2687 "\n"
2688 "#ifdef USESHADOWMAPVSDCT\n"
2689 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2690 "#endif\n"
2691 "\n"
2692 "#if defined(USESHADOWMAP2D)\n"
2693 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2694 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2695 "#endif\n"
2696 "\n"
2697 "out float4 gl_FragData0 : COLOR0,\n"
2698 "out float4 gl_FragData1 : COLOR1\n"
2699 ")\n"
2700 "{\n"
2701 "       // calculate viewspace pixel position\n"
2702 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2703 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2704 "       float3 position;\n"
2705 "#ifdef HLSL\n"
2706 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2707 "#else\n"
2708 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2709 "#endif\n"
2710 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2711 "       // decode viewspace pixel normal\n"
2712 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2713 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2714 "       // surfacenormal = pixel normal in viewspace\n"
2715 "       // LightVector = pixel to light in viewspace\n"
2716 "       // CubeVector = position in lightspace\n"
2717 "       // eyevector = pixel to view in viewspace\n"
2718 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2719 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2720 "#ifdef USEDIFFUSE\n"
2721 "       // calculate diffuse shading\n"
2722 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2723 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2724 "#endif\n"
2725 "#ifdef USESPECULAR\n"
2726 "       // calculate directional shading\n"
2727 "       float3 eyevector = position * -1.0;\n"
2728 "#  ifdef USEEXACTSPECULARMATH\n"
2729 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2730 "#  else\n"
2731 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2732 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2733 "#  endif\n"
2734 "#endif\n"
2735 "\n"
2736 "#if defined(USESHADOWMAP2D)\n"
2737 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2738 "#ifdef USESHADOWMAPVSDCT\n"
2739 ", Texture_CubeProjection\n"
2740 "#endif\n"
2741 "       ));\n"
2742 "#endif\n"
2743 "\n"
2744 "#ifdef USEDIFFUSE\n"
2745 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2746 "#else\n"
2747 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2748 "#endif\n"
2749 "#ifdef USESPECULAR\n"
2750 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2751 "#else\n"
2752 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2753 "#endif\n"
2754 "\n"
2755 "# ifdef USECUBEFILTER\n"
2756 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2757 "       gl_FragData0.rgb *= cubecolor;\n"
2758 "       gl_FragData1.rgb *= cubecolor;\n"
2759 "# endif\n"
2760 "}\n"
2761 "#endif // FRAGMENT_SHADER\n"
2762 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2763 "\n"
2764 "\n"
2765 "\n"
2766 "\n"
2767 "#ifdef VERTEX_SHADER\n"
2768 "void main\n"
2769 "(\n"
2770 "float4 gl_Vertex : POSITION,\n"
2771 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2772 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2773 "float4 gl_Color : COLOR0,\n"
2774 "#endif\n"
2775 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2776 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2777 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2778 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2779 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2780 "\n"
2781 "uniform float3 EyePosition : register(c24),\n"
2782 "uniform float4x4 TexMatrix : register(c0),\n"
2783 "#ifdef USEVERTEXTEXTUREBLEND\n"
2784 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2785 "#endif\n"
2786 "#ifdef MODE_LIGHTSOURCE\n"
2787 "uniform float4x4 ModelToLight : register(c20),\n"
2788 "#endif\n"
2789 "#ifdef MODE_LIGHTSOURCE\n"
2790 "uniform float3 LightPosition : register(c27),\n"
2791 "#endif\n"
2792 "#ifdef MODE_LIGHTDIRECTION\n"
2793 "uniform float3 LightDir : register(c26),\n"
2794 "#endif\n"
2795 "uniform float4 FogPlane : register(c25),\n"
2796 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2797 "uniform float3 LightPosition : register(c27),\n"
2798 "#endif\n"
2799 "#ifdef USESHADOWMAPORTHO\n"
2800 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2801 "#endif\n"
2802 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2803 "out float4 gl_FrontColor : COLOR,\n"
2804 "#endif\n"
2805 "out float4 TexCoordBoth : TEXCOORD0,\n"
2806 "#ifdef USELIGHTMAP\n"
2807 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2808 "#endif\n"
2809 "#ifdef USEEYEVECTOR\n"
2810 "out float3 EyeVector : TEXCOORD2,\n"
2811 "#endif\n"
2812 "#ifdef USEREFLECTION\n"
2813 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2814 "#endif\n"
2815 "#ifdef USEFOG\n"
2816 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2817 "#endif\n"
2818 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2819 "out float3 LightVector : TEXCOORD1,\n"
2820 "#endif\n"
2821 "#ifdef MODE_LIGHTSOURCE\n"
2822 "out float3 CubeVector : TEXCOORD3,\n"
2823 "#endif\n"
2824 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2825 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2826 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2827 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2828 "#endif\n"
2829 "#ifdef USESHADOWMAPORTHO\n"
2830 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2831 "#endif\n"
2832 "out float4 gl_Position : POSITION\n"
2833 ")\n"
2834 "{\n"
2835 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2836 "#ifdef HLSL\n"
2837 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2838 "#else\n"
2839 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2840 "#endif\n"
2841 "#endif\n"
2842 "       // copy the surface texcoord\n"
2843 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2844 "#ifdef USEVERTEXTEXTUREBLEND\n"
2845 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2846 "#endif\n"
2847 "#ifdef USELIGHTMAP\n"
2848 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2849 "#endif\n"
2850 "\n"
2851 "#ifdef MODE_LIGHTSOURCE\n"
2852 "       // transform vertex position into light attenuation/cubemap space\n"
2853 "       // (-1 to +1 across the light box)\n"
2854 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2855 "\n"
2856 "# ifdef USEDIFFUSE\n"
2857 "       // transform unnormalized light direction into tangent space\n"
2858 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2859 "       //  normalize it per pixel)\n"
2860 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2861 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2862 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2863 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2864 "# endif\n"
2865 "#endif\n"
2866 "\n"
2867 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2868 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2869 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2870 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2871 "#endif\n"
2872 "\n"
2873 "       // transform unnormalized eye direction into tangent space\n"
2874 "#ifdef USEEYEVECTOR\n"
2875 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2876 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2877 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2878 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2879 "#endif\n"
2880 "\n"
2881 "#ifdef USEFOG\n"
2882 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2883 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2884 "#endif\n"
2885 "\n"
2886 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2887 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2888 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2889 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2890 "#endif\n"
2891 "\n"
2892 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2893 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2894 "\n"
2895 "#ifdef USESHADOWMAPORTHO\n"
2896 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2897 "#endif\n"
2898 "\n"
2899 "#ifdef USEREFLECTION\n"
2900 "       ModelViewProjectionPosition = gl_Position;\n"
2901 "#endif\n"
2902 "}\n"
2903 "#endif // VERTEX_SHADER\n"
2904 "\n"
2905 "\n"
2906 "\n"
2907 "\n"
2908 "#ifdef FRAGMENT_SHADER\n"
2909 "void main\n"
2910 "(\n"
2911 "#ifdef USEDEFERREDLIGHTMAP\n"
2912 "#ifdef HLSL\n"
2913 "float2 Pixel : VPOS,\n"
2914 "#else\n"
2915 "float2 Pixel : WPOS,\n"
2916 "#endif\n"
2917 "#endif\n"
2918 "float4 gl_FrontColor : COLOR,\n"
2919 "float4 TexCoordBoth : TEXCOORD0,\n"
2920 "#ifdef USELIGHTMAP\n"
2921 "float2 TexCoordLightmap : TEXCOORD1,\n"
2922 "#endif\n"
2923 "#ifdef USEEYEVECTOR\n"
2924 "float3 EyeVector : TEXCOORD2,\n"
2925 "#endif\n"
2926 "#ifdef USEREFLECTION\n"
2927 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2928 "#endif\n"
2929 "#ifdef USEFOG\n"
2930 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2931 "#endif\n"
2932 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2933 "float3 LightVector : TEXCOORD1,\n"
2934 "#endif\n"
2935 "#ifdef MODE_LIGHTSOURCE\n"
2936 "float3 CubeVector : TEXCOORD3,\n"
2937 "#endif\n"
2938 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2939 "float4 ModelViewPosition : TEXCOORD0,\n"
2940 "#endif\n"
2941 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2942 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2943 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2944 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2945 "#endif\n"
2946 "#ifdef USESHADOWMAPORTHO\n"
2947 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2948 "#endif\n"
2949 "\n"
2950 "uniform sampler Texture_Normal : register(s0),\n"
2951 "uniform sampler Texture_Color : register(s1),\n"
2952 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2953 "uniform sampler Texture_Gloss : register(s2),\n"
2954 "#endif\n"
2955 "#ifdef USEGLOW\n"
2956 "uniform sampler Texture_Glow : register(s3),\n"
2957 "#endif\n"
2958 "#ifdef USEVERTEXTEXTUREBLEND\n"
2959 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2960 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2961 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2962 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2963 "#endif\n"
2964 "#ifdef USEGLOW\n"
2965 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2966 "#endif\n"
2967 "#endif\n"
2968 "#ifdef USECOLORMAPPING\n"
2969 "uniform sampler Texture_Pants : register(s4),\n"
2970 "uniform sampler Texture_Shirt : register(s7),\n"
2971 "#endif\n"
2972 "#ifdef USEFOG\n"
2973 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2974 "uniform sampler Texture_FogMask : register(s8),\n"
2975 "#endif\n"
2976 "#ifdef USELIGHTMAP\n"
2977 "uniform sampler Texture_Lightmap : register(s9),\n"
2978 "#endif\n"
2979 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2980 "uniform sampler Texture_Deluxemap : register(s10),\n"
2981 "#endif\n"
2982 "#ifdef USEREFLECTION\n"
2983 "uniform sampler Texture_Reflection : register(s7),\n"
2984 "#endif\n"
2985 "\n"
2986 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2987 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2988 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2989 "#endif\n"
2990 "#ifdef USEDEFERREDLIGHTMAP\n"
2991 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2992 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2993 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2994 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2995 "#endif\n"
2996 "\n"
2997 "#ifdef USECOLORMAPPING\n"
2998 "uniform half3 Color_Pants : register(c7),\n"
2999 "uniform half3 Color_Shirt : register(c8),\n"
3000 "#endif\n"
3001 "#ifdef USEFOG\n"
3002 "uniform float3 FogColor : register(c16),\n"
3003 "uniform float FogRangeRecip : register(c20),\n"
3004 "uniform float FogPlaneViewDist : register(c19),\n"
3005 "uniform float FogHeightFade : register(c17),\n"
3006 "#endif\n"
3007 "\n"
3008 "#ifdef USEOFFSETMAPPING\n"
3009 "uniform float OffsetMapping_Scale : register(c24),\n"
3010 "#endif\n"
3011 "\n"
3012 "#ifdef USEDEFERREDLIGHTMAP\n"
3013 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3014 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3015 "uniform half3 DeferredMod_Specular : register(c13),\n"
3016 "#endif\n"
3017 "uniform half3 Color_Ambient : register(c3),\n"
3018 "uniform half3 Color_Diffuse : register(c4),\n"
3019 "uniform half3 Color_Specular : register(c5),\n"
3020 "uniform half SpecularPower : register(c36),\n"
3021 "#ifdef USEGLOW\n"
3022 "uniform half3 Color_Glow : register(c6),\n"
3023 "#endif\n"
3024 "uniform half Alpha : register(c0),\n"
3025 "#ifdef USEREFLECTION\n"
3026 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3027 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3028 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3029 "uniform half4 ReflectColor : register(c26),\n"
3030 "#endif\n"
3031 "#ifdef USEREFLECTCUBE\n"
3032 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3033 "uniform sampler Texture_ReflectMask : register(s5),\n"
3034 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3035 "#endif\n"
3036 "#ifdef MODE_LIGHTDIRECTION\n"
3037 "uniform half3 LightColor : register(c21),\n"
3038 "#endif\n"
3039 "#ifdef MODE_LIGHTSOURCE\n"
3040 "uniform half3 LightColor : register(c21),\n"
3041 "#endif\n"
3042 "\n"
3043 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3044 "uniform sampler Texture_Attenuation : register(s9),\n"
3045 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3046 "#endif\n"
3047 "\n"
3048 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3049 "\n"
3050 "#ifdef USESHADOWMAP2D\n"
3051 "# ifdef USESHADOWSAMPLER\n"
3052 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3053 "# else\n"
3054 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3055 "# endif\n"
3056 "#endif\n"
3057 "\n"
3058 "#ifdef USESHADOWMAPVSDCT\n"
3059 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3060 "#endif\n"
3061 "\n"
3062 "#if defined(USESHADOWMAP2D)\n"
3063 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3064 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3065 "#endif\n"
3066 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3067 "\n"
3068 "out float4 gl_FragColor : COLOR\n"
3069 ")\n"
3070 "{\n"
3071 "       float2 TexCoord = TexCoordBoth.xy;\n"
3072 "#ifdef USEVERTEXTEXTUREBLEND\n"
3073 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3074 "#endif\n"
3075 "#ifdef USEOFFSETMAPPING\n"
3076 "       // apply offsetmapping\n"
3077 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3078 "#define TexCoord TexCoordOffset\n"
3079 "#endif\n"
3080 "\n"
3081 "       // combine the diffuse textures (base, pants, shirt)\n"
3082 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3083 "#ifdef USEALPHAKILL\n"
3084 "       if (color.a < 0.5)\n"
3085 "               discard;\n"
3086 "#endif\n"
3087 "       color.a *= Alpha;\n"
3088 "#ifdef USECOLORMAPPING\n"
3089 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3090 "#endif\n"
3091 "#ifdef USEVERTEXTEXTUREBLEND\n"
3092 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3093 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3094 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3095 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3096 "       color.a = 1.0;\n"
3097 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3098 "#endif\n"
3099 "\n"
3100 "       // get the surface normal\n"
3101 "#ifdef USEVERTEXTEXTUREBLEND\n"
3102 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3103 "#else\n"
3104 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3105 "#endif\n"
3106 "\n"
3107 "       // get the material colors\n"
3108 "       half3 diffusetex = color.rgb;\n"
3109 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3110 "# ifdef USEVERTEXTEXTUREBLEND\n"
3111 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3112 "# else\n"
3113 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3114 "# endif\n"
3115 "#endif\n"
3116 "\n"
3117 "#ifdef USEREFLECTCUBE\n"
3118 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3119 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3120 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3121 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3122 "#endif\n"
3123 "\n"
3124 "\n"
3125 "\n"
3126 "\n"
3127 "#ifdef MODE_LIGHTSOURCE\n"
3128 "       // light source\n"
3129 "#ifdef USEDIFFUSE\n"
3130 "       half3 lightnormal = half3(normalize(LightVector));\n"
3131 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3132 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3133 "#ifdef USESPECULAR\n"
3134 "#ifdef USEEXACTSPECULARMATH\n"
3135 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3136 "#else\n"
3137 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3138 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3139 "#endif\n"
3140 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3141 "#endif\n"
3142 "#else\n"
3143 "       color.rgb = diffusetex * Color_Ambient;\n"
3144 "#endif\n"
3145 "       color.rgb *= LightColor;\n"
3146 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3147 "#if defined(USESHADOWMAP2D)\n"
3148 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3149 "#ifdef USESHADOWMAPVSDCT\n"
3150 ", Texture_CubeProjection\n"
3151 "#endif\n"
3152 "       ));\n"
3153 "\n"
3154 "#endif\n"
3155 "# ifdef USECUBEFILTER\n"
3156 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3157 "# endif\n"
3158 "\n"
3159 "#ifdef USESHADOWMAP2D\n"
3160 "#ifdef USESHADOWMAPVSDCT\n"
3161 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3162 "#else\n"
3163 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3164 "#endif\n"
3165 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3166 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3167 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3168 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3169 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3170 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3171 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3172 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3173 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3174 "//     color.r = half(shadowmaptc.z);\n"
3175 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3176 "//     color.r = half(shadowmaptc.z);\n"
3177 "//     color.r = 1;\n"
3178 "//     color.rgb = abs(CubeVector);\n"
3179 "#endif\n"
3180 "//     color.rgb = half3(1,1,1);\n"
3181 "#endif // MODE_LIGHTSOURCE\n"
3182 "\n"
3183 "\n"
3184 "\n"
3185 "\n"
3186 "#ifdef MODE_LIGHTDIRECTION\n"
3187 "#define SHADING\n"
3188 "#ifdef USEDIFFUSE\n"
3189 "       half3 lightnormal = half3(normalize(LightVector));\n"
3190 "#endif\n"
3191 "#define lightcolor LightColor\n"
3192 "#endif // MODE_LIGHTDIRECTION\n"
3193 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3194 "#define SHADING\n"
3195 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3196 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3197 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3198 "       // convert modelspace light vector to tangentspace\n"
3199 "       half3 lightnormal;\n"
3200 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3201 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3202 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3203 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3204 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3205 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3206 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3207 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3208 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3209 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3210 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3211 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3212 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3213 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3214 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3215 "#define SHADING\n"
3216 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3217 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3218 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3219 "#endif\n"
3220 "\n"
3221 "\n"
3222 "\n"
3223 "\n"
3224 "#ifdef MODE_FAKELIGHT\n"
3225 "#define SHADING\n"
3226 "half3 lightnormal = half3(normalize(EyeVector));\n"
3227 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3228 "#endif // MODE_FAKELIGHT\n"
3229 "\n"
3230 "\n"
3231 "\n"
3232 "\n"
3233 "#ifdef MODE_LIGHTMAP\n"
3234 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3235 "#endif // MODE_LIGHTMAP\n"
3236 "#ifdef MODE_VERTEXCOLOR\n"
3237 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3238 "#endif // MODE_VERTEXCOLOR\n"
3239 "#ifdef MODE_FLATCOLOR\n"
3240 "       color.rgb = diffusetex * Color_Ambient;\n"
3241 "#endif // MODE_FLATCOLOR\n"
3242 "\n"
3243 "\n"
3244 "\n"
3245 "\n"
3246 "#ifdef SHADING\n"
3247 "# ifdef USEDIFFUSE\n"
3248 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3249 "#  ifdef USESPECULAR\n"
3250 "#   ifdef USEEXACTSPECULARMATH\n"
3251 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3252 "#   else\n"
3253 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3254 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3255 "#   endif\n"
3256 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3257 "#  else\n"
3258 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3259 "#  endif\n"
3260 "# else\n"
3261 "       color.rgb = diffusetex * Color_Ambient;\n"
3262 "# endif\n"
3263 "#endif\n"
3264 "\n"
3265 "#ifdef USESHADOWMAPORTHO\n"
3266 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3267 "#endif\n"
3268 "\n"
3269 "#ifdef USEDEFERREDLIGHTMAP\n"
3270 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3271 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3272 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3273 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3274 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3275 "#endif\n"
3276 "\n"
3277 "#ifdef USEGLOW\n"
3278 "#ifdef USEVERTEXTEXTUREBLEND\n"
3279 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3280 "#else\n"
3281 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3282 "#endif\n"
3283 "#endif\n"
3284 "\n"
3285 "#ifdef USEFOG\n"
3286 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3287 "#endif\n"
3288 "\n"
3289 "       // 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"
3290 "#ifdef USEREFLECTION\n"
3291 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3292 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3293 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3294 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3295 "       // FIXME temporary hack to detect the case that the reflection\n"
3296 "       // gets blackened at edges due to leaving the area that contains actual\n"
3297 "       // content.\n"
3298 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3299 "       // 'appening.\n"
3300 "       float 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 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3304 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3305 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3306 "#endif\n"
3307 "\n"
3308 "       gl_FragColor = float4(color);\n"
3309 "}\n"
3310 "#endif // FRAGMENT_SHADER\n"
3311 "\n"
3312 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3313 "#endif // !MODE_DEFERREDGEOMETRY\n"
3314 "#endif // !MODE_WATER\n"
3315 "#endif // !MODE_REFRACTION\n"
3316 "#endif // !MODE_BLOOMBLUR\n"
3317 "#endif // !MODE_GENERIC\n"
3318 "#endif // !MODE_POSTPROCESS\n"
3319 "#endif // !MODE_SHOWDEPTH\n"
3320 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3321 ;
3322
3323 char *glslshaderstring = NULL;
3324 char *cgshaderstring = NULL;
3325 char *hlslshaderstring = NULL;
3326
3327 //=======================================================================================================================================================
3328
3329 typedef struct shaderpermutationinfo_s
3330 {
3331         const char *pretext;
3332         const char *name;
3333 }
3334 shaderpermutationinfo_t;
3335
3336 typedef struct shadermodeinfo_s
3337 {
3338         const char *vertexfilename;
3339         const char *geometryfilename;
3340         const char *fragmentfilename;
3341         const char *pretext;
3342         const char *name;
3343 }
3344 shadermodeinfo_t;
3345
3346 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3347 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3348 {
3349         {"#define USEDIFFUSE\n", " diffuse"},
3350         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3351         {"#define USEVIEWTINT\n", " viewtint"},
3352         {"#define USECOLORMAPPING\n", " colormapping"},
3353         {"#define USESATURATION\n", " saturation"},
3354         {"#define USEFOGINSIDE\n", " foginside"},
3355         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3356         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3357         {"#define USEGAMMARAMPS\n", " gammaramps"},
3358         {"#define USECUBEFILTER\n", " cubefilter"},
3359         {"#define USEGLOW\n", " glow"},
3360         {"#define USEBLOOM\n", " bloom"},
3361         {"#define USESPECULAR\n", " specular"},
3362         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3363         {"#define USEREFLECTION\n", " reflection"},
3364         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3365         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3366         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3367         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3368         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3369         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3370         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3371         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3372         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3373         {"#define USEALPHAKILL\n", " alphakill"},
3374         {"#define USEREFLECTCUBE\n", " reflectcube"},
3375         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3376 };
3377
3378 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3379 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3380 {
3381         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3382         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3383         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3384         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3385         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3386         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3387         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3388         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3389         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3390         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3391         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3392         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3393         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3394         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3395         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3396         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3397 };
3398
3399 #ifdef SUPPORTCG
3400 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3401 {
3402         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3403         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3404         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3405         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3406         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3407         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3408         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3409         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3410         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3411         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3412         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3413         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3414         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3415         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3416         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3417         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3418 };
3419 #endif
3420
3421 #ifdef SUPPORTD3D
3422 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3423 {
3424         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3425         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3426         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3427         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3428         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3429         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3430         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3431         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3432         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3433         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3434         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3435         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3436         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3437         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3438         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3439         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3440 };
3441 #endif
3442
3443 struct r_glsl_permutation_s;
3444 typedef struct r_glsl_permutation_s
3445 {
3446         /// hash lookup data
3447         struct r_glsl_permutation_s *hashnext;
3448         unsigned int mode;
3449         unsigned int permutation;
3450
3451         /// indicates if we have tried compiling this permutation already
3452         qboolean compiled;
3453         /// 0 if compilation failed
3454         int program;
3455         /// locations of detected uniforms in program object, or -1 if not found
3456         int loc_Texture_First;
3457         int loc_Texture_Second;
3458         int loc_Texture_GammaRamps;
3459         int loc_Texture_Normal;
3460         int loc_Texture_Color;
3461         int loc_Texture_Gloss;
3462         int loc_Texture_Glow;
3463         int loc_Texture_SecondaryNormal;
3464         int loc_Texture_SecondaryColor;
3465         int loc_Texture_SecondaryGloss;
3466         int loc_Texture_SecondaryGlow;
3467         int loc_Texture_Pants;
3468         int loc_Texture_Shirt;
3469         int loc_Texture_FogHeightTexture;
3470         int loc_Texture_FogMask;
3471         int loc_Texture_Lightmap;
3472         int loc_Texture_Deluxemap;
3473         int loc_Texture_Attenuation;
3474         int loc_Texture_Cube;
3475         int loc_Texture_Refraction;
3476         int loc_Texture_Reflection;
3477         int loc_Texture_ShadowMap2D;
3478         int loc_Texture_CubeProjection;
3479         int loc_Texture_ScreenDepth;
3480         int loc_Texture_ScreenNormalMap;
3481         int loc_Texture_ScreenDiffuse;
3482         int loc_Texture_ScreenSpecular;
3483         int loc_Texture_ReflectMask;
3484         int loc_Texture_ReflectCube;
3485         int loc_Alpha;
3486         int loc_BloomBlur_Parameters;
3487         int loc_ClientTime;
3488         int loc_Color_Ambient;
3489         int loc_Color_Diffuse;
3490         int loc_Color_Specular;
3491         int loc_Color_Glow;
3492         int loc_Color_Pants;
3493         int loc_Color_Shirt;
3494         int loc_DeferredColor_Ambient;
3495         int loc_DeferredColor_Diffuse;
3496         int loc_DeferredColor_Specular;
3497         int loc_DeferredMod_Diffuse;
3498         int loc_DeferredMod_Specular;
3499         int loc_DistortScaleRefractReflect;
3500         int loc_EyePosition;
3501         int loc_FogColor;
3502         int loc_FogHeightFade;
3503         int loc_FogPlane;
3504         int loc_FogPlaneViewDist;
3505         int loc_FogRangeRecip;
3506         int loc_LightColor;
3507         int loc_LightDir;
3508         int loc_LightPosition;
3509         int loc_OffsetMapping_Scale;
3510         int loc_PixelSize;
3511         int loc_ReflectColor;
3512         int loc_ReflectFactor;
3513         int loc_ReflectOffset;
3514         int loc_RefractColor;
3515         int loc_Saturation;
3516         int loc_ScreenCenterRefractReflect;
3517         int loc_ScreenScaleRefractReflect;
3518         int loc_ScreenToDepth;
3519         int loc_ShadowMap_Parameters;
3520         int loc_ShadowMap_TextureScale;
3521         int loc_SpecularPower;
3522         int loc_UserVec1;
3523         int loc_UserVec2;
3524         int loc_UserVec3;
3525         int loc_UserVec4;
3526         int loc_ViewTintColor;
3527         int loc_ViewToLight;
3528         int loc_ModelToLight;
3529         int loc_TexMatrix;
3530         int loc_BackgroundTexMatrix;
3531         int loc_ModelViewProjectionMatrix;
3532         int loc_ModelViewMatrix;
3533         int loc_PixelToScreenTexCoord;
3534         int loc_ModelToReflectCube;
3535         int loc_ShadowMapMatrix;
3536         int loc_BloomColorSubtract;
3537         int loc_NormalmapScrollBlend;
3538 }
3539 r_glsl_permutation_t;
3540
3541 #define SHADERPERMUTATION_HASHSIZE 256
3542
3543
3544 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3545 // these can NOT degrade! only use for simple stuff
3546 enum
3547 {
3548         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3549         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3550         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3551         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3552         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3553         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3554 };
3555 #define SHADERSTATICPARMS_COUNT 6
3556
3557 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3558 static int shaderstaticparms_count = 0;
3559
3560 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3561 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3562 qboolean R_CompileShader_CheckStaticParms(void)
3563 {
3564         static int r_compileshader_staticparms_save[1];
3565         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3566         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3567
3568         // detect all
3569         if (r_glsl_saturation_redcompensate.integer)
3570                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3571         if (r_shadow_glossexact.integer)
3572                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3573         if (r_glsl_postprocess.integer)
3574         {
3575                 if (r_glsl_postprocess_uservec1_enable.integer)
3576                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3577                 if (r_glsl_postprocess_uservec2_enable.integer)
3578                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3579                 if (r_glsl_postprocess_uservec3_enable.integer)
3580                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3581                 if (r_glsl_postprocess_uservec4_enable.integer)
3582                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3583         }
3584         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3585 }
3586
3587 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3588         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3589                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3590         else \
3591                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3592 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3593 {
3594         shaderstaticparms_count = 0;
3595
3596         // emit all
3597         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3598         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3599         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3600         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3601         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3602         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3603 }
3604
3605 /// information about each possible shader permutation
3606 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3607 /// currently selected permutation
3608 r_glsl_permutation_t *r_glsl_permutation;
3609 /// storage for permutations linked in the hash table
3610 memexpandablearray_t r_glsl_permutationarray;
3611
3612 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3613 {
3614         //unsigned int hashdepth = 0;
3615         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3616         r_glsl_permutation_t *p;
3617         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3618         {
3619                 if (p->mode == mode && p->permutation == permutation)
3620                 {
3621                         //if (hashdepth > 10)
3622                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3623                         return p;
3624                 }
3625                 //hashdepth++;
3626         }
3627         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3628         p->mode = mode;
3629         p->permutation = permutation;
3630         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3631         r_glsl_permutationhash[mode][hashindex] = p;
3632         //if (hashdepth > 10)
3633         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3634         return p;
3635 }
3636
3637 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3638 {
3639         char *shaderstring;
3640         if (!filename || !filename[0])
3641                 return NULL;
3642         if (!strcmp(filename, "glsl/default.glsl"))
3643         {
3644                 if (!glslshaderstring)
3645                 {
3646                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3647                         if (glslshaderstring)
3648                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3649                         else
3650                                 glslshaderstring = (char *)builtinshaderstring;
3651                 }
3652                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3653                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3654                 return shaderstring;
3655         }
3656         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3657         if (shaderstring)
3658         {
3659                 if (printfromdisknotice)
3660                         Con_DPrintf("from disk %s... ", filename);
3661                 return shaderstring;
3662         }
3663         return shaderstring;
3664 }
3665
3666 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3667 {
3668         int i;
3669         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3670         char *vertexstring, *geometrystring, *fragmentstring;
3671         char permutationname[256];
3672         int vertstrings_count = 0;
3673         int geomstrings_count = 0;
3674         int fragstrings_count = 0;
3675         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3676         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3677         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3678
3679         if (p->compiled)
3680                 return;
3681         p->compiled = true;
3682         p->program = 0;
3683
3684         permutationname[0] = 0;
3685         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3686         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3687         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3688
3689         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3690
3691         // the first pretext is which type of shader to compile as
3692         // (later these will all be bound together as a program object)
3693         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3694         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3695         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3696
3697         // the second pretext is the mode (for example a light source)
3698         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3699         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3700         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3701         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3702
3703         // now add all the permutation pretexts
3704         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3705         {
3706                 if (permutation & (1<<i))
3707                 {
3708                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3709                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3710                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3711                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3712                 }
3713                 else
3714                 {
3715                         // keep line numbers correct
3716                         vertstrings_list[vertstrings_count++] = "\n";
3717                         geomstrings_list[geomstrings_count++] = "\n";
3718                         fragstrings_list[fragstrings_count++] = "\n";
3719                 }
3720         }
3721
3722         // add static parms
3723         R_CompileShader_AddStaticParms(mode, permutation);
3724         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3725         vertstrings_count += shaderstaticparms_count;
3726         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3727         geomstrings_count += shaderstaticparms_count;
3728         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3729         fragstrings_count += shaderstaticparms_count;
3730
3731         // now append the shader text itself
3732         vertstrings_list[vertstrings_count++] = vertexstring;
3733         geomstrings_list[geomstrings_count++] = geometrystring;
3734         fragstrings_list[fragstrings_count++] = fragmentstring;
3735
3736         // if any sources were NULL, clear the respective list
3737         if (!vertexstring)
3738                 vertstrings_count = 0;
3739         if (!geometrystring)
3740                 geomstrings_count = 0;
3741         if (!fragmentstring)
3742                 fragstrings_count = 0;
3743
3744         // compile the shader program
3745         if (vertstrings_count + geomstrings_count + fragstrings_count)
3746                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3747         if (p->program)
3748         {
3749                 CHECKGLERROR
3750                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3751                 // look up all the uniform variable names we care about, so we don't
3752                 // have to look them up every time we set them
3753
3754                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3755                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3756                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3757                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3758                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3759                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3760                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3761                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3762                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3763                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3764                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3765                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3766                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3767                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3768                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3769                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3770                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3771                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3772                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3773                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3774                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3775                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3776                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3777                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3778                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3779                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3780                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3781                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3782                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3783                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3784                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3785                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3786                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3787                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3788                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3789                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3790                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3791                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3792                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3793                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3794                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3795                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3796                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3797                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3798                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3799                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3800                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3801                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3802                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3803                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3804                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3805                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3806                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3807                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3808                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3809                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3810                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3811                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3812                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3813                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3814                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3815                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3816                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3817                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3818                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3819                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3820                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3821                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3822                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3823                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3824                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3825                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3826                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3827                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3828                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3829                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3830                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3831                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3832                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3833                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3834                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3835                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3836                 // initialize the samplers to refer to the texture units we use
3837                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3838                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3839                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3840                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3841                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3842                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3843                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3844                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3845                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3846                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3847                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3848                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3849                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3850                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3851                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3852                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3853                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3854                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3855                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3856                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3857                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3858                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3859                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3860                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3861                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3862                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3863                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3864                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3865                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3866                 CHECKGLERROR
3867                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3868         }
3869         else
3870                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3871
3872         // free the strings
3873         if (vertexstring)
3874                 Mem_Free(vertexstring);
3875         if (geometrystring)
3876                 Mem_Free(geometrystring);
3877         if (fragmentstring)
3878                 Mem_Free(fragmentstring);
3879 }
3880
3881 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3882 {
3883         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3884         if (r_glsl_permutation != perm)
3885         {
3886                 r_glsl_permutation = perm;
3887                 if (!r_glsl_permutation->program)
3888                 {
3889                         if (!r_glsl_permutation->compiled)
3890                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3891                         if (!r_glsl_permutation->program)
3892                         {
3893                                 // remove features until we find a valid permutation
3894                                 int i;
3895                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3896                                 {
3897                                         // reduce i more quickly whenever it would not remove any bits
3898                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3899                                         if (!(permutation & j))
3900                                                 continue;
3901                                         permutation -= j;
3902                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3903                                         if (!r_glsl_permutation->compiled)
3904                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3905                                         if (r_glsl_permutation->program)
3906                                                 break;
3907                                 }
3908                                 if (i >= SHADERPERMUTATION_COUNT)
3909                                 {
3910                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3911                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3912                                         qglUseProgramObjectARB(0);CHECKGLERROR
3913                                         return; // no bit left to clear, entire mode is broken
3914                                 }
3915                         }
3916                 }
3917                 CHECKGLERROR
3918                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3919         }
3920         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3921         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3922         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3923 }
3924
3925 #ifdef SUPPORTCG
3926 #include <Cg/cgGL.h>
3927 struct r_cg_permutation_s;
3928 typedef struct r_cg_permutation_s
3929 {
3930         /// hash lookup data
3931         struct r_cg_permutation_s *hashnext;
3932         unsigned int mode;
3933         unsigned int permutation;
3934
3935         /// indicates if we have tried compiling this permutation already
3936         qboolean compiled;
3937         /// 0 if compilation failed
3938         CGprogram vprogram;
3939         CGprogram fprogram;
3940         /// locations of detected parameters in programs, or NULL if not found
3941         CGparameter vp_EyePosition;
3942         CGparameter vp_FogPlane;
3943         CGparameter vp_LightDir;
3944         CGparameter vp_LightPosition;
3945         CGparameter vp_ModelToLight;
3946         CGparameter vp_TexMatrix;
3947         CGparameter vp_BackgroundTexMatrix;
3948         CGparameter vp_ModelViewProjectionMatrix;
3949         CGparameter vp_ModelViewMatrix;
3950         CGparameter vp_ShadowMapMatrix;
3951
3952         CGparameter fp_Texture_First;
3953         CGparameter fp_Texture_Second;
3954         CGparameter fp_Texture_GammaRamps;
3955         CGparameter fp_Texture_Normal;
3956         CGparameter fp_Texture_Color;
3957         CGparameter fp_Texture_Gloss;
3958         CGparameter fp_Texture_Glow;
3959         CGparameter fp_Texture_SecondaryNormal;
3960         CGparameter fp_Texture_SecondaryColor;
3961         CGparameter fp_Texture_SecondaryGloss;
3962         CGparameter fp_Texture_SecondaryGlow;
3963         CGparameter fp_Texture_Pants;
3964         CGparameter fp_Texture_Shirt;
3965         CGparameter fp_Texture_FogHeightTexture;
3966         CGparameter fp_Texture_FogMask;
3967         CGparameter fp_Texture_Lightmap;
3968         CGparameter fp_Texture_Deluxemap;
3969         CGparameter fp_Texture_Attenuation;
3970         CGparameter fp_Texture_Cube;
3971         CGparameter fp_Texture_Refraction;
3972         CGparameter fp_Texture_Reflection;
3973         CGparameter fp_Texture_ShadowMap2D;
3974         CGparameter fp_Texture_CubeProjection;
3975         CGparameter fp_Texture_ScreenDepth;
3976         CGparameter fp_Texture_ScreenNormalMap;
3977         CGparameter fp_Texture_ScreenDiffuse;
3978         CGparameter fp_Texture_ScreenSpecular;
3979         CGparameter fp_Texture_ReflectMask;
3980         CGparameter fp_Texture_ReflectCube;
3981         CGparameter fp_Alpha;
3982         CGparameter fp_BloomBlur_Parameters;
3983         CGparameter fp_ClientTime;
3984         CGparameter fp_Color_Ambient;
3985         CGparameter fp_Color_Diffuse;
3986         CGparameter fp_Color_Specular;
3987         CGparameter fp_Color_Glow;
3988         CGparameter fp_Color_Pants;
3989         CGparameter fp_Color_Shirt;
3990         CGparameter fp_DeferredColor_Ambient;
3991         CGparameter fp_DeferredColor_Diffuse;
3992         CGparameter fp_DeferredColor_Specular;
3993         CGparameter fp_DeferredMod_Diffuse;
3994         CGparameter fp_DeferredMod_Specular;
3995         CGparameter fp_DistortScaleRefractReflect;
3996         CGparameter fp_EyePosition;
3997         CGparameter fp_FogColor;
3998         CGparameter fp_FogHeightFade;
3999         CGparameter fp_FogPlane;
4000         CGparameter fp_FogPlaneViewDist;
4001         CGparameter fp_FogRangeRecip;
4002         CGparameter fp_LightColor;
4003         CGparameter fp_LightDir;
4004         CGparameter fp_LightPosition;
4005         CGparameter fp_OffsetMapping_Scale;
4006         CGparameter fp_PixelSize;
4007         CGparameter fp_ReflectColor;
4008         CGparameter fp_ReflectFactor;
4009         CGparameter fp_ReflectOffset;
4010         CGparameter fp_RefractColor;
4011         CGparameter fp_Saturation;
4012         CGparameter fp_ScreenCenterRefractReflect;
4013         CGparameter fp_ScreenScaleRefractReflect;
4014         CGparameter fp_ScreenToDepth;
4015         CGparameter fp_ShadowMap_Parameters;
4016         CGparameter fp_ShadowMap_TextureScale;
4017         CGparameter fp_SpecularPower;
4018         CGparameter fp_UserVec1;
4019         CGparameter fp_UserVec2;
4020         CGparameter fp_UserVec3;
4021         CGparameter fp_UserVec4;
4022         CGparameter fp_ViewTintColor;
4023         CGparameter fp_ViewToLight;
4024         CGparameter fp_PixelToScreenTexCoord;
4025         CGparameter fp_ModelToReflectCube;
4026         CGparameter fp_BloomColorSubtract;
4027         CGparameter fp_NormalmapScrollBlend;
4028 }
4029 r_cg_permutation_t;
4030
4031 /// information about each possible shader permutation
4032 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4033 /// currently selected permutation
4034 r_cg_permutation_t *r_cg_permutation;
4035 /// storage for permutations linked in the hash table
4036 memexpandablearray_t r_cg_permutationarray;
4037
4038 #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));}}
4039
4040 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4041 {
4042         //unsigned int hashdepth = 0;
4043         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4044         r_cg_permutation_t *p;
4045         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4046         {
4047                 if (p->mode == mode && p->permutation == permutation)
4048                 {
4049                         //if (hashdepth > 10)
4050                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4051                         return p;
4052                 }
4053                 //hashdepth++;
4054         }
4055         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4056         p->mode = mode;
4057         p->permutation = permutation;
4058         p->hashnext = r_cg_permutationhash[mode][hashindex];
4059         r_cg_permutationhash[mode][hashindex] = p;
4060         //if (hashdepth > 10)
4061         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4062         return p;
4063 }
4064
4065 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4066 {
4067         char *shaderstring;
4068         if (!filename || !filename[0])
4069                 return NULL;
4070         if (!strcmp(filename, "cg/default.cg"))
4071         {
4072                 if (!cgshaderstring)
4073                 {
4074                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4075                         if (cgshaderstring)
4076                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4077                         else
4078                                 cgshaderstring = (char *)builtincgshaderstring;
4079                 }
4080                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4081                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4082                 return shaderstring;
4083         }
4084         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4085         if (shaderstring)
4086         {
4087                 if (printfromdisknotice)
4088                         Con_DPrintf("from disk %s... ", filename);
4089                 return shaderstring;
4090         }
4091         return shaderstring;
4092 }
4093
4094 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4095 {
4096         // TODO: load or create .fp and .vp shader files
4097 }
4098
4099 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4100 {
4101         int i;
4102         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4103         int vertstring_length = 0;
4104         int geomstring_length = 0;
4105         int fragstring_length = 0;
4106         char *t;
4107         char *vertexstring, *geometrystring, *fragmentstring;
4108         char *vertstring, *geomstring, *fragstring;
4109         char permutationname[256];
4110         char cachename[256];
4111         CGprofile vertexProfile;
4112         CGprofile fragmentProfile;
4113         int vertstrings_count = 0;
4114         int geomstrings_count = 0;
4115         int fragstrings_count = 0;
4116         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4117         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4118         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4119
4120         if (p->compiled)
4121                 return;
4122         p->compiled = true;
4123         p->vprogram = NULL;
4124         p->fprogram = NULL;
4125
4126         permutationname[0] = 0;
4127         cachename[0] = 0;
4128         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4129         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4130         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4131
4132         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4133         strlcat(cachename, "cg/", sizeof(cachename));
4134
4135         // the first pretext is which type of shader to compile as
4136         // (later these will all be bound together as a program object)
4137         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4138         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4139         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4140
4141         // the second pretext is the mode (for example a light source)
4142         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4143         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4144         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4145         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4146         strlcat(cachename, modeinfo->name, sizeof(cachename));
4147
4148         // now add all the permutation pretexts
4149         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4150         {
4151                 if (permutation & (1<<i))
4152                 {
4153                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4154                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4155                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4156                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4157                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4158                 }
4159                 else
4160                 {
4161                         // keep line numbers correct
4162                         vertstrings_list[vertstrings_count++] = "\n";
4163                         geomstrings_list[geomstrings_count++] = "\n";
4164                         fragstrings_list[fragstrings_count++] = "\n";
4165                 }
4166         }
4167
4168         // add static parms
4169         R_CompileShader_AddStaticParms(mode, permutation);
4170         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4171         vertstrings_count += shaderstaticparms_count;
4172         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4173         geomstrings_count += shaderstaticparms_count;
4174         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4175         fragstrings_count += shaderstaticparms_count;
4176
4177         // replace spaces in the cachename with _ characters
4178         for (i = 0;cachename[i];i++)
4179                 if (cachename[i] == ' ')
4180                         cachename[i] = '_';
4181
4182         // now append the shader text itself
4183         vertstrings_list[vertstrings_count++] = vertexstring;
4184         geomstrings_list[geomstrings_count++] = geometrystring;
4185         fragstrings_list[fragstrings_count++] = fragmentstring;
4186
4187         // if any sources were NULL, clear the respective list
4188         if (!vertexstring)
4189                 vertstrings_count = 0;
4190         if (!geometrystring)
4191                 geomstrings_count = 0;
4192         if (!fragmentstring)
4193                 fragstrings_count = 0;
4194
4195         vertstring_length = 0;
4196         for (i = 0;i < vertstrings_count;i++)
4197                 vertstring_length += strlen(vertstrings_list[i]);
4198         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4199         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4200                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4201
4202         geomstring_length = 0;
4203         for (i = 0;i < geomstrings_count;i++)
4204                 geomstring_length += strlen(geomstrings_list[i]);
4205         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4206         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4207                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4208
4209         fragstring_length = 0;
4210         for (i = 0;i < fragstrings_count;i++)
4211                 fragstring_length += strlen(fragstrings_list[i]);
4212         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4213         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4214                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4215
4216         CHECKGLERROR
4217         CHECKCGERROR
4218         //vertexProfile = CG_PROFILE_ARBVP1;
4219         //fragmentProfile = CG_PROFILE_ARBFP1;
4220         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4221         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4222         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4223         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4224         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4225         CHECKGLERROR
4226
4227         // try to load the cached shader, or generate one
4228         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4229
4230         // if caching failed, do a dynamic compile for now
4231         CHECKCGERROR
4232         if (vertstring[0] && !p->vprogram)
4233                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4234         CHECKCGERROR
4235         if (fragstring[0] && !p->fprogram)
4236                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4237         CHECKCGERROR
4238
4239         // look up all the uniform variable names we care about, so we don't
4240         // have to look them up every time we set them
4241         if (p->vprogram)
4242         {
4243                 CHECKCGERROR
4244                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4245                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4246                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4247                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4248                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4249                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4250                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4251                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4252                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4253                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4254                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4255                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4256                 CHECKCGERROR
4257         }
4258         if (p->fprogram)
4259         {
4260                 CHECKCGERROR
4261                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4262                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4263                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4264                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4265                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4266                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4267                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4268                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4269                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4270                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4271                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4272                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4273                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4274                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4275                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4276                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4277                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4278                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4279                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4280                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4281                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4282                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4283                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4284                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4285                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4286                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4287                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4288                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4289                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4290                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4291                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4292                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4293                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4294                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4295                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4296                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4297                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4298                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4299                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4300                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4301                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4302                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4303                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4304                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4305                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4306                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4307                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4308                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4309                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4310                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4311                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4312                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4313                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4314                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4315                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4316                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4317                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4318                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4319                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4320                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4321                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4322                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4323                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4324                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4325                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4326                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4327                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4328                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4329                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4330                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4331                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4332                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4333                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4334                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4335                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4336                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4337                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4338                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4339                 CHECKCGERROR
4340         }
4341
4342         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4343                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4344         else
4345                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4346
4347         // free the strings
4348         if (vertstring)
4349                 Mem_Free(vertstring);
4350         if (geomstring)
4351                 Mem_Free(geomstring);
4352         if (fragstring)
4353                 Mem_Free(fragstring);
4354         if (vertexstring)
4355                 Mem_Free(vertexstring);
4356         if (geometrystring)
4357                 Mem_Free(geometrystring);
4358         if (fragmentstring)
4359                 Mem_Free(fragmentstring);
4360 }
4361
4362 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4363 {
4364         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4365         CHECKGLERROR
4366         CHECKCGERROR
4367         if (r_cg_permutation != perm)
4368         {
4369                 r_cg_permutation = perm;
4370                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4371                 {
4372                         if (!r_cg_permutation->compiled)
4373                                 R_CG_CompilePermutation(perm, mode, permutation);
4374                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4375                         {
4376                                 // remove features until we find a valid permutation
4377                                 int i;
4378                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4379                                 {
4380                                         // reduce i more quickly whenever it would not remove any bits
4381                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4382                                         if (!(permutation & j))
4383                                                 continue;
4384                                         permutation -= j;
4385                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4386                                         if (!r_cg_permutation->compiled)
4387                                                 R_CG_CompilePermutation(perm, mode, permutation);
4388                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4389                                                 break;
4390                                 }
4391                                 if (i >= SHADERPERMUTATION_COUNT)
4392                                 {
4393                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4394                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4395                                         return; // no bit left to clear, entire mode is broken
4396                                 }
4397                         }
4398                 }
4399                 CHECKGLERROR
4400                 CHECKCGERROR
4401                 if (r_cg_permutation->vprogram)
4402                 {
4403                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4404                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4405                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4406                 }
4407                 else
4408                 {
4409                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4410                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4411                 }
4412                 if (r_cg_permutation->fprogram)
4413                 {
4414                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4415                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4416                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4417                 }
4418                 else
4419                 {
4420                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4421                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4422                 }
4423         }
4424         CHECKCGERROR
4425         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4426         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4427         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4428 }
4429
4430 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4431 {
4432         cgGLSetTextureParameter(param, R_GetTexture(tex));
4433         cgGLEnableTextureParameter(param);
4434 }
4435 #endif
4436
4437 #ifdef SUPPORTD3D
4438
4439 #ifdef SUPPORTD3D
4440 #include <d3d9.h>
4441 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4442 extern D3DCAPS9 vid_d3d9caps;
4443 #endif
4444
4445 struct r_hlsl_permutation_s;
4446 typedef struct r_hlsl_permutation_s
4447 {
4448         /// hash lookup data
4449         struct r_hlsl_permutation_s *hashnext;
4450         unsigned int mode;
4451         unsigned int permutation;
4452
4453         /// indicates if we have tried compiling this permutation already
4454         qboolean compiled;
4455         /// NULL if compilation failed
4456         IDirect3DVertexShader9 *vertexshader;
4457         IDirect3DPixelShader9 *pixelshader;
4458 }
4459 r_hlsl_permutation_t;
4460
4461 typedef enum D3DVSREGISTER_e
4462 {
4463         D3DVSREGISTER_TexMatrix = 0, // float4x4
4464         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4465         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4466         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4467         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4468         D3DVSREGISTER_ModelToLight = 20, // float4x4
4469         D3DVSREGISTER_EyePosition = 24,
4470         D3DVSREGISTER_FogPlane = 25,
4471         D3DVSREGISTER_LightDir = 26,
4472         D3DVSREGISTER_LightPosition = 27,
4473 }
4474 D3DVSREGISTER_t;
4475
4476 typedef enum D3DPSREGISTER_e
4477 {
4478         D3DPSREGISTER_Alpha = 0,
4479         D3DPSREGISTER_BloomBlur_Parameters = 1,
4480         D3DPSREGISTER_ClientTime = 2,
4481         D3DPSREGISTER_Color_Ambient = 3,
4482         D3DPSREGISTER_Color_Diffuse = 4,
4483         D3DPSREGISTER_Color_Specular = 5,
4484         D3DPSREGISTER_Color_Glow = 6,
4485         D3DPSREGISTER_Color_Pants = 7,
4486         D3DPSREGISTER_Color_Shirt = 8,
4487         D3DPSREGISTER_DeferredColor_Ambient = 9,
4488         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4489         D3DPSREGISTER_DeferredColor_Specular = 11,
4490         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4491         D3DPSREGISTER_DeferredMod_Specular = 13,
4492         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4493         D3DPSREGISTER_EyePosition = 15, // unused
4494         D3DPSREGISTER_FogColor = 16,
4495         D3DPSREGISTER_FogHeightFade = 17,
4496         D3DPSREGISTER_FogPlane = 18,
4497         D3DPSREGISTER_FogPlaneViewDist = 19,
4498         D3DPSREGISTER_FogRangeRecip = 20,
4499         D3DPSREGISTER_LightColor = 21,
4500         D3DPSREGISTER_LightDir = 22, // unused
4501         D3DPSREGISTER_LightPosition = 23,
4502         D3DPSREGISTER_OffsetMapping_Scale = 24,
4503         D3DPSREGISTER_PixelSize = 25,
4504         D3DPSREGISTER_ReflectColor = 26,
4505         D3DPSREGISTER_ReflectFactor = 27,
4506         D3DPSREGISTER_ReflectOffset = 28,
4507         D3DPSREGISTER_RefractColor = 29,
4508         D3DPSREGISTER_Saturation = 30,
4509         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4510         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4511         D3DPSREGISTER_ScreenToDepth = 33,
4512         D3DPSREGISTER_ShadowMap_Parameters = 34,
4513         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4514         D3DPSREGISTER_SpecularPower = 36,
4515         D3DPSREGISTER_UserVec1 = 37,
4516         D3DPSREGISTER_UserVec2 = 38,
4517         D3DPSREGISTER_UserVec3 = 39,
4518         D3DPSREGISTER_UserVec4 = 40,
4519         D3DPSREGISTER_ViewTintColor = 41,
4520         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4521         D3DPSREGISTER_BloomColorSubtract = 43,
4522         D3DPSREGISTER_ViewToLight = 44, // float4x4
4523         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4524         D3DPSREGISTER_NormalmapScrollBlend = 52,
4525         // next at 53
4526 }
4527 D3DPSREGISTER_t;
4528
4529 /// information about each possible shader permutation
4530 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4531 /// currently selected permutation
4532 r_hlsl_permutation_t *r_hlsl_permutation;
4533 /// storage for permutations linked in the hash table
4534 memexpandablearray_t r_hlsl_permutationarray;
4535
4536 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4537 {
4538         //unsigned int hashdepth = 0;
4539         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4540         r_hlsl_permutation_t *p;
4541         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4542         {
4543                 if (p->mode == mode && p->permutation == permutation)
4544                 {
4545                         //if (hashdepth > 10)
4546                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4547                         return p;
4548                 }
4549                 //hashdepth++;
4550         }
4551         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4552         p->mode = mode;
4553         p->permutation = permutation;
4554         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4555         r_hlsl_permutationhash[mode][hashindex] = p;
4556         //if (hashdepth > 10)
4557         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4558         return p;
4559 }
4560
4561 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4562 {
4563         char *shaderstring;
4564         if (!filename || !filename[0])
4565                 return NULL;
4566         if (!strcmp(filename, "hlsl/default.hlsl"))
4567         {
4568                 if (!hlslshaderstring)
4569                 {
4570                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4571                         if (hlslshaderstring)
4572                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4573                         else
4574                                 hlslshaderstring = (char *)builtincgshaderstring;
4575                 }
4576                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4577                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4578                 return shaderstring;
4579         }
4580         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4581         if (shaderstring)
4582         {
4583                 if (printfromdisknotice)
4584                         Con_DPrintf("from disk %s... ", filename);
4585                 return shaderstring;
4586         }
4587         return shaderstring;
4588 }
4589
4590 #include <d3dx9.h>
4591 //#include <d3dx9shader.h>
4592 //#include <d3dx9mesh.h>
4593
4594 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4595 {
4596         DWORD *vsbin = NULL;
4597         DWORD *psbin = NULL;
4598         fs_offset_t vsbinsize;
4599         fs_offset_t psbinsize;
4600 //      IDirect3DVertexShader9 *vs = NULL;
4601 //      IDirect3DPixelShader9 *ps = NULL;
4602         ID3DXBuffer *vslog = NULL;
4603         ID3DXBuffer *vsbuffer = NULL;
4604         ID3DXConstantTable *vsconstanttable = NULL;
4605         ID3DXBuffer *pslog = NULL;
4606         ID3DXBuffer *psbuffer = NULL;
4607         ID3DXConstantTable *psconstanttable = NULL;
4608         int vsresult = 0;
4609         int psresult = 0;
4610         char temp[MAX_INPUTLINE];
4611         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4612         qboolean debugshader = gl_paranoid.integer != 0;
4613         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4614         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4615         if (!debugshader)
4616         {
4617                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4618                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4619         }
4620         if ((!vsbin && vertstring) || (!psbin && fragstring))
4621         {
4622                 const char* dllnames_d3dx9 [] =
4623                 {
4624                         "d3dx9_43.dll",
4625                         "d3dx9_42.dll",
4626                         "d3dx9_41.dll",
4627                         "d3dx9_40.dll",
4628                         "d3dx9_39.dll",
4629                         "d3dx9_38.dll",
4630                         "d3dx9_37.dll",
4631                         "d3dx9_36.dll",
4632                         "d3dx9_35.dll",
4633                         "d3dx9_34.dll",
4634                         "d3dx9_33.dll",
4635                         "d3dx9_32.dll",
4636                         "d3dx9_31.dll",
4637                         "d3dx9_30.dll",
4638                         "d3dx9_29.dll",
4639                         "d3dx9_28.dll",
4640                         "d3dx9_27.dll",
4641                         "d3dx9_26.dll",
4642                         "d3dx9_25.dll",
4643                         "d3dx9_24.dll",
4644                         NULL
4645                 };
4646                 dllhandle_t d3dx9_dll = NULL;
4647                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4648                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4649                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4650                 dllfunction_t d3dx9_dllfuncs[] =
4651                 {
4652                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4653                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4654                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4655                         {NULL, NULL}
4656                 };
4657                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4658                 {
4659                         DWORD shaderflags = 0;
4660                         if (debugshader)
4661                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4662                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4663                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4664                         if (vertstring && vertstring[0])
4665                         {
4666                                 if (debugshader)
4667                                 {
4668 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4669 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4670                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4671                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4672                                 }
4673                                 else
4674                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4675                                 if (vsbuffer)
4676                                 {
4677                                         vsbinsize = vsbuffer->GetBufferSize();
4678                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4679                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4680                                         vsbuffer->Release();
4681                                 }
4682                                 if (vslog)
4683                                 {
4684                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4685                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4686                                         vslog->Release();
4687                                 }
4688                         }
4689                         if (fragstring && fragstring[0])
4690                         {
4691                                 if (debugshader)
4692                                 {
4693 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4694 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4695                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4696                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4697                                 }
4698                                 else
4699                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4700                                 if (psbuffer)
4701                                 {
4702                                         psbinsize = psbuffer->GetBufferSize();
4703                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4704                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4705                                         psbuffer->Release();
4706                                 }
4707                                 if (pslog)
4708                                 {
4709                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4710                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4711                                         pslog->Release();
4712                                 }
4713                         }
4714                         Sys_UnloadLibrary(&d3dx9_dll);
4715                 }
4716                 else
4717                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4718         }
4719         if (vsbin && psbin)
4720         {
4721                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4722                 if (FAILED(vsresult))
4723                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4724                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4725                 if (FAILED(psresult))
4726                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4727         }
4728         // free the shader data
4729         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4730         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4731 }
4732
4733 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4734 {
4735         int i;
4736         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4737         int vertstring_length = 0;
4738         int geomstring_length = 0;
4739         int fragstring_length = 0;
4740         char *t;
4741         char *vertexstring, *geometrystring, *fragmentstring;
4742         char *vertstring, *geomstring, *fragstring;
4743         char permutationname[256];
4744         char cachename[256];
4745         int vertstrings_count = 0;
4746         int geomstrings_count = 0;
4747         int fragstrings_count = 0;
4748         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4749         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4750         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4751
4752         if (p->compiled)
4753                 return;
4754         p->compiled = true;
4755         p->vertexshader = NULL;
4756         p->pixelshader = NULL;
4757
4758         permutationname[0] = 0;
4759         cachename[0] = 0;
4760         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4761         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4762         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4763
4764         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4765         strlcat(cachename, "hlsl/", sizeof(cachename));
4766
4767         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4768         vertstrings_count = 0;
4769         geomstrings_count = 0;
4770         fragstrings_count = 0;
4771         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4772         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4773         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4774
4775         // the first pretext is which type of shader to compile as
4776         // (later these will all be bound together as a program object)
4777         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4778         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4779         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4780
4781         // the second pretext is the mode (for example a light source)
4782         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4783         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4784         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4785         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4786         strlcat(cachename, modeinfo->name, sizeof(cachename));
4787
4788         // now add all the permutation pretexts
4789         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4790         {
4791                 if (permutation & (1<<i))
4792                 {
4793                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4794                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4795                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4796                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4797                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4798                 }
4799                 else
4800                 {
4801                         // keep line numbers correct
4802                         vertstrings_list[vertstrings_count++] = "\n";
4803                         geomstrings_list[geomstrings_count++] = "\n";
4804                         fragstrings_list[fragstrings_count++] = "\n";
4805                 }
4806         }
4807
4808         // add static parms
4809         R_CompileShader_AddStaticParms(mode, permutation);
4810         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4811         vertstrings_count += shaderstaticparms_count;
4812         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4813         geomstrings_count += shaderstaticparms_count;
4814         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4815         fragstrings_count += shaderstaticparms_count;
4816
4817         // replace spaces in the cachename with _ characters
4818         for (i = 0;cachename[i];i++)
4819                 if (cachename[i] == ' ')
4820                         cachename[i] = '_';
4821
4822         // now append the shader text itself
4823         vertstrings_list[vertstrings_count++] = vertexstring;
4824         geomstrings_list[geomstrings_count++] = geometrystring;
4825         fragstrings_list[fragstrings_count++] = fragmentstring;
4826
4827         // if any sources were NULL, clear the respective list
4828         if (!vertexstring)
4829                 vertstrings_count = 0;
4830         if (!geometrystring)
4831                 geomstrings_count = 0;
4832         if (!fragmentstring)
4833                 fragstrings_count = 0;
4834
4835         vertstring_length = 0;
4836         for (i = 0;i < vertstrings_count;i++)
4837                 vertstring_length += strlen(vertstrings_list[i]);
4838         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4839         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4840                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4841
4842         geomstring_length = 0;
4843         for (i = 0;i < geomstrings_count;i++)
4844                 geomstring_length += strlen(geomstrings_list[i]);
4845         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4846         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4847                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4848
4849         fragstring_length = 0;
4850         for (i = 0;i < fragstrings_count;i++)
4851                 fragstring_length += strlen(fragstrings_list[i]);
4852         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4853         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4854                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4855
4856         // try to load the cached shader, or generate one
4857         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4858
4859         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4860                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4861         else
4862                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4863
4864         // free the strings
4865         if (vertstring)
4866                 Mem_Free(vertstring);
4867         if (geomstring)
4868                 Mem_Free(geomstring);
4869         if (fragstring)
4870                 Mem_Free(fragstring);
4871         if (vertexstring)
4872                 Mem_Free(vertexstring);
4873         if (geometrystring)
4874                 Mem_Free(geometrystring);
4875         if (fragmentstring)
4876                 Mem_Free(fragmentstring);
4877 }
4878
4879 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4880 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4881 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);}
4882 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);}
4883 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);}
4884 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);}
4885
4886 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4887 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4888 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);}
4889 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);}
4890 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);}
4891 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);}
4892
4893 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4894 {
4895         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4896         if (r_hlsl_permutation != perm)
4897         {
4898                 r_hlsl_permutation = perm;
4899                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4900                 {
4901                         if (!r_hlsl_permutation->compiled)
4902                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4903                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4904                         {
4905                                 // remove features until we find a valid permutation
4906                                 int i;
4907                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4908                                 {
4909                                         // reduce i more quickly whenever it would not remove any bits
4910                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4911                                         if (!(permutation & j))
4912                                                 continue;
4913                                         permutation -= j;
4914                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4915                                         if (!r_hlsl_permutation->compiled)
4916                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4917                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4918                                                 break;
4919                                 }
4920                                 if (i >= SHADERPERMUTATION_COUNT)
4921                                 {
4922                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4923                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4924                                         return; // no bit left to clear, entire mode is broken
4925                                 }
4926                         }
4927                 }
4928                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4929                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4930         }
4931         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4932         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4933         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4934 }
4935 #endif
4936
4937 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4938 {
4939         DPSOFTRAST_SetShader(mode, permutation);
4940         DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4941         DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4942         DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4943 }
4944
4945 void R_GLSL_Restart_f(void)
4946 {
4947         unsigned int i, limit;
4948         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4949                 Mem_Free(glslshaderstring);
4950         glslshaderstring = NULL;
4951         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4952                 Mem_Free(cgshaderstring);
4953         cgshaderstring = NULL;
4954         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4955                 Mem_Free(hlslshaderstring);
4956         hlslshaderstring = NULL;
4957         switch(vid.renderpath)
4958         {
4959         case RENDERPATH_D3D9:
4960 #ifdef SUPPORTD3D
4961                 {
4962                         r_hlsl_permutation_t *p;
4963                         r_hlsl_permutation = NULL;
4964 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4965 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4966 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4967 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4968                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4969                         for (i = 0;i < limit;i++)
4970                         {
4971                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4972                                 {
4973                                         if (p->vertexshader)
4974                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4975                                         if (p->pixelshader)
4976                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4977                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4978                                 }
4979                         }
4980                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4981                 }
4982 #endif
4983                 break;
4984         case RENDERPATH_D3D10:
4985                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4986                 break;
4987         case RENDERPATH_D3D11:
4988                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4989                 break;
4990         case RENDERPATH_GL20:
4991                 {
4992                         r_glsl_permutation_t *p;
4993                         r_glsl_permutation = NULL;
4994                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4995                         for (i = 0;i < limit;i++)
4996                         {
4997                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4998                                 {
4999                                         GL_Backend_FreeProgram(p->program);
5000                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5001                                 }
5002                         }
5003                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5004                 }
5005                 break;
5006         case RENDERPATH_CGGL:
5007 #ifdef SUPPORTCG
5008                 {
5009                         r_cg_permutation_t *p;
5010                         r_cg_permutation = NULL;
5011                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5012                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5013                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5014                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5015                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5016                         for (i = 0;i < limit;i++)
5017                         {
5018                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5019                                 {
5020                                         if (p->vprogram)
5021                                                 cgDestroyProgram(p->vprogram);
5022                                         if (p->fprogram)
5023                                                 cgDestroyProgram(p->fprogram);
5024                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5025                                 }
5026                         }
5027                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5028                 }
5029 #endif
5030                 break;
5031         case RENDERPATH_GL13:
5032         case RENDERPATH_GL11:
5033                 break;
5034         case RENDERPATH_SOFT:
5035                 break;
5036         }
5037 }
5038
5039 void R_GLSL_DumpShader_f(void)
5040 {
5041         int i;
5042         qfile_t *file;
5043
5044         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5045         if (file)
5046         {
5047                 FS_Print(file, "/* The engine may define the following macros:\n");
5048                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5049                 for (i = 0;i < SHADERMODE_COUNT;i++)
5050                         FS_Print(file, glslshadermodeinfo[i].pretext);
5051                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5052                         FS_Print(file, shaderpermutationinfo[i].pretext);
5053                 FS_Print(file, "*/\n");
5054                 FS_Print(file, builtinshaderstring);
5055                 FS_Close(file);
5056                 Con_Printf("glsl/default.glsl written\n");
5057         }
5058         else
5059                 Con_Printf("failed to write to glsl/default.glsl\n");
5060
5061 #ifdef SUPPORTCG
5062         file = FS_OpenRealFile("cg/default.cg", "w", false);
5063         if (file)
5064         {
5065                 FS_Print(file, "/* The engine may define the following macros:\n");
5066                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5067                 for (i = 0;i < SHADERMODE_COUNT;i++)
5068                         FS_Print(file, cgshadermodeinfo[i].pretext);
5069                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5070                         FS_Print(file, shaderpermutationinfo[i].pretext);
5071                 FS_Print(file, "*/\n");
5072                 FS_Print(file, builtincgshaderstring);
5073                 FS_Close(file);
5074                 Con_Printf("cg/default.cg written\n");
5075         }
5076         else
5077                 Con_Printf("failed to write to cg/default.cg\n");
5078 #endif
5079
5080 #ifdef SUPPORTD3D
5081         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5082         if (file)
5083         {
5084                 FS_Print(file, "/* The engine may define the following macros:\n");
5085                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5086                 for (i = 0;i < SHADERMODE_COUNT;i++)
5087                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5088                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5089                         FS_Print(file, shaderpermutationinfo[i].pretext);
5090                 FS_Print(file, "*/\n");
5091                 FS_Print(file, builtincgshaderstring);
5092                 FS_Close(file);
5093                 Con_Printf("hlsl/default.hlsl written\n");
5094         }
5095         else
5096                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5097 #endif
5098 }
5099
5100 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5101 {
5102         if (!second)
5103                 texturemode = GL_MODULATE;
5104         switch (vid.renderpath)
5105         {
5106         case RENDERPATH_D3D9:
5107 #ifdef SUPPORTD3D
5108                 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))));
5109                 R_Mesh_TexBind(GL20TU_FIRST , first );
5110                 R_Mesh_TexBind(GL20TU_SECOND, second);
5111 #endif
5112                 break;
5113         case RENDERPATH_D3D10:
5114                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5115                 break;
5116         case RENDERPATH_D3D11:
5117                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5118                 break;
5119         case RENDERPATH_GL20:
5120                 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))));
5121                 R_Mesh_TexBind(GL20TU_FIRST , first );
5122                 R_Mesh_TexBind(GL20TU_SECOND, second);
5123                 break;
5124         case RENDERPATH_CGGL:
5125 #ifdef SUPPORTCG
5126                 CHECKCGERROR
5127                 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))));
5128                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5129                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5130 #endif
5131                 break;
5132         case RENDERPATH_GL13:
5133                 R_Mesh_TexBind(0, first );
5134                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5135                 R_Mesh_TexBind(1, second);
5136                 if (second)
5137                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5138                 break;
5139         case RENDERPATH_GL11:
5140                 R_Mesh_TexBind(0, first );
5141                 break;
5142         case RENDERPATH_SOFT:
5143                 R_SetupShader_SetPermutationSoft(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))));
5144                 R_Mesh_TexBind(GL20TU_FIRST , first );
5145                 R_Mesh_TexBind(GL20TU_SECOND, second);
5146                 break;
5147         }
5148 }
5149
5150 void R_SetupShader_DepthOrShadow(void)
5151 {
5152         switch (vid.renderpath)
5153         {
5154         case RENDERPATH_D3D9:
5155 #ifdef SUPPORTD3D
5156                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
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_DEPTH_OR_SHADOW, 0);
5167                 break;
5168         case RENDERPATH_CGGL:
5169 #ifdef SUPPORTCG
5170                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5171 #endif
5172                 break;
5173         case RENDERPATH_GL13:
5174                 R_Mesh_TexBind(0, 0);
5175                 R_Mesh_TexBind(1, 0);
5176                 break;
5177         case RENDERPATH_GL11:
5178                 R_Mesh_TexBind(0, 0);
5179                 break;
5180         case RENDERPATH_SOFT:
5181                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
5182                 break;
5183         }
5184 }
5185
5186 void R_SetupShader_ShowDepth(void)
5187 {
5188         switch (vid.renderpath)
5189         {
5190         case RENDERPATH_D3D9:
5191 #ifdef SUPPORTHLSL
5192                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5193 #endif
5194                 break;
5195         case RENDERPATH_D3D10:
5196                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5197                 break;
5198         case RENDERPATH_D3D11:
5199                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5200                 break;
5201         case RENDERPATH_GL20:
5202                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5203                 break;
5204         case RENDERPATH_CGGL:
5205 #ifdef SUPPORTCG
5206                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5207 #endif
5208                 break;
5209         case RENDERPATH_GL13:
5210                 break;
5211         case RENDERPATH_GL11:
5212                 break;
5213         case RENDERPATH_SOFT:
5214                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
5215                 break;
5216         }
5217 }
5218
5219 extern qboolean r_shadow_usingdeferredprepass;
5220 extern cvar_t r_shadow_deferred_8bitrange;
5221 extern rtexture_t *r_shadow_attenuationgradienttexture;
5222 extern rtexture_t *r_shadow_attenuation2dtexture;
5223 extern rtexture_t *r_shadow_attenuation3dtexture;
5224 extern qboolean r_shadow_usingshadowmap2d;
5225 extern qboolean r_shadow_usingshadowmaportho;
5226 extern float r_shadow_shadowmap_texturescale[2];
5227 extern float r_shadow_shadowmap_parameters[4];
5228 extern qboolean r_shadow_shadowmapvsdct;
5229 extern qboolean r_shadow_shadowmapsampler;
5230 extern int r_shadow_shadowmappcf;
5231 extern rtexture_t *r_shadow_shadowmap2dtexture;
5232 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5233 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5234 extern matrix4x4_t r_shadow_shadowmapmatrix;
5235 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5236 extern int r_shadow_prepass_width;
5237 extern int r_shadow_prepass_height;
5238 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5239 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5240 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5241 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5242 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5243 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5244 {
5245         // a blendfunc allows colormod if:
5246         // a) it can never keep the destination pixel invariant, or
5247         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5248         // this is to prevent unintended side effects from colormod
5249
5250         // in formulas:
5251         // IF there is a (s, sa) for which for all (d, da),
5252         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5253         // THEN, for this (s, sa) and all (colormod, d, da):
5254         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5255         // OBVIOUSLY, this means that
5256         //   s*colormod * src(s*colormod, d, sa, da) = 0
5257         //   dst(s*colormod, d, sa, da)              = 1
5258
5259         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5260
5261         // main condition to leave dst color invariant:
5262         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5263         //   src == GL_ZERO:
5264         //     s * 0 + d * dst(s, d, sa, da) == d
5265         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5266         //       => colormod is a problem for GL_SRC_COLOR only
5267         //   src == GL_ONE:
5268         //     s + d * dst(s, d, sa, da) == d
5269         //       => s == 0
5270         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5271         //       => colormod is never problematic for these
5272         //   src == GL_SRC_COLOR:
5273         //     s*s + d * dst(s, d, sa, da) == d
5274         //       => s == 0
5275         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5276         //       => colormod is never problematic for these
5277         //   src == GL_ONE_MINUS_SRC_COLOR:
5278         //     s*(1-s) + d * dst(s, d, sa, da) == d
5279         //       => s == 0 or s == 1
5280         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5281         //       => colormod is a problem for GL_SRC_COLOR only
5282         //   src == GL_DST_COLOR
5283         //     s*d + d * dst(s, d, sa, da) == d
5284         //       => s == 1
5285         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5286         //       => colormod is always a problem
5287         //     or
5288         //       => s == 0
5289         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5290         //       => colormod is never problematic for these
5291         //       => BUT, we do not know s! We must assume it is problematic
5292         //       then... except in GL_ONE case, where we know all invariant
5293         //       cases are fine
5294         //   src == GL_ONE_MINUS_DST_COLOR
5295         //     s*(1-d) + d * dst(s, d, sa, da) == d
5296         //       => s == 0 (1-d is impossible to handle for our desired result)
5297         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5298         //       => colormod is never problematic for these
5299         //   src == GL_SRC_ALPHA
5300         //     s*sa + d * dst(s, d, sa, da) == d
5301         //       => s == 0, or sa == 0
5302         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5303         //       => colormod breaks in the case GL_SRC_COLOR only
5304         //   src == GL_ONE_MINUS_SRC_ALPHA
5305         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5306         //       => s == 0, or sa == 1
5307         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5308         //       => colormod breaks in the case GL_SRC_COLOR only
5309         //   src == GL_DST_ALPHA
5310         //     s*da + d * dst(s, d, sa, da) == d
5311         //       => s == 0
5312         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5313         //       => colormod is never problematic for these
5314
5315         switch(src)
5316         {
5317                 case GL_ZERO:
5318                 case GL_ONE_MINUS_SRC_COLOR:
5319                 case GL_SRC_ALPHA:
5320                 case GL_ONE_MINUS_SRC_ALPHA:
5321                         if(dst == GL_SRC_COLOR)
5322                                 return false;
5323                         return true;
5324                 case GL_ONE:
5325                 case GL_SRC_COLOR:
5326                 case GL_ONE_MINUS_DST_COLOR:
5327                 case GL_DST_ALPHA:
5328                 case GL_ONE_MINUS_DST_ALPHA:
5329                         return true;
5330                 case GL_DST_COLOR:
5331                         if(dst == GL_ONE)
5332                                 return true;
5333                         return false;
5334                 default:
5335                         return false;
5336         }
5337 }
5338 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)
5339 {
5340         // select a permutation of the lighting shader appropriate to this
5341         // combination of texture, entity, light source, and fogging, only use the
5342         // minimum features necessary to avoid wasting rendering time in the
5343         // fragment shader on features that are not being used
5344         unsigned int permutation = 0;
5345         unsigned int mode = 0;
5346         qboolean allow_colormod;
5347         static float dummy_colormod[3] = {1, 1, 1};
5348         float *colormod = rsurface.colormod;
5349         float m16f[16];
5350         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5351         if (rsurfacepass == RSURFPASS_BACKGROUND)
5352         {
5353                 // distorted background
5354                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5355                 {
5356                         mode = SHADERMODE_WATER;
5357                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5358                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5359                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
5360                         {
5361                                 // this is the right thing to do for wateralpha
5362                                 GL_BlendFunc(GL_ONE, GL_ZERO);
5363                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5364                         }
5365                         else
5366                         {
5367                                 // this is the right thing to do for entity alpha
5368                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5369                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5370                         }
5371                 }
5372                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5373                 {
5374                         mode = SHADERMODE_REFRACTION;
5375                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5376                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5377                 }
5378                 else
5379                 {
5380                         mode = SHADERMODE_GENERIC;
5381                         permutation |= SHADERPERMUTATION_DIFFUSE;
5382                         GL_BlendFunc(GL_ONE, GL_ZERO);
5383                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5384                 }
5385                 GL_AlphaTest(false);
5386         }
5387         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5388         {
5389                 if (r_glsl_offsetmapping.integer)
5390                 {
5391                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5392                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5393                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5394                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5395                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5396                         {
5397                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5398                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5399                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5400                         }
5401                 }
5402                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5403                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5404                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5405                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5406                 // normalmap (deferred prepass), may use alpha test on diffuse
5407                 mode = SHADERMODE_DEFERREDGEOMETRY;
5408                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5409                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5410                 GL_AlphaTest(false);
5411                 GL_BlendFunc(GL_ONE, GL_ZERO);
5412                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5413         }
5414         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5415         {
5416                 if (r_glsl_offsetmapping.integer)
5417                 {
5418                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5419                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5420                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5421                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5422                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5423                         {
5424                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5425                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5426                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5427                         }
5428                 }
5429                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5430                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5431                 // light source
5432                 mode = SHADERMODE_LIGHTSOURCE;
5433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5434                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5435                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5436                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5437                 if (diffusescale > 0)
5438                         permutation |= SHADERPERMUTATION_DIFFUSE;
5439                 if (specularscale > 0)
5440                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5441                 if (r_refdef.fogenabled)
5442                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5443                 if (rsurface.texture->colormapping)
5444                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5445                 if (r_shadow_usingshadowmap2d)
5446                 {
5447                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5448                         if(r_shadow_shadowmapvsdct)
5449                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5450
5451                         if (r_shadow_shadowmapsampler)
5452                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5453                         if (r_shadow_shadowmappcf > 1)
5454                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5455                         else if (r_shadow_shadowmappcf)
5456                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5457                 }
5458                 if (rsurface.texture->reflectmasktexture)
5459                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5460                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5461                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5462                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5463         }
5464         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5465         {
5466                 if (r_glsl_offsetmapping.integer)
5467                 {
5468                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5469                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5470                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5471                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5472                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5473                         {
5474                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5475                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5476                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5477                         }
5478                 }
5479                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5480                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5481                 // unshaded geometry (fullbright or ambient model lighting)
5482                 mode = SHADERMODE_FLATCOLOR;
5483                 ambientscale = diffusescale = specularscale = 0;
5484                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5485                         permutation |= SHADERPERMUTATION_GLOW;
5486                 if (r_refdef.fogenabled)
5487                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5488                 if (rsurface.texture->colormapping)
5489                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5490                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5491                 {
5492                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5493                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5494
5495                         if (r_shadow_shadowmapsampler)
5496                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5497                         if (r_shadow_shadowmappcf > 1)
5498                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5499                         else if (r_shadow_shadowmappcf)
5500                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5501                 }
5502                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5503                         permutation |= SHADERPERMUTATION_REFLECTION;
5504                 if (rsurface.texture->reflectmasktexture)
5505                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5506                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5507                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5508                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5509         }
5510         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5511         {
5512                 if (r_glsl_offsetmapping.integer)
5513                 {
5514                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5515                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5516                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5517                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5518                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5519                         {
5520                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5521                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5522                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5523                         }
5524                 }
5525                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5526                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5527                 // directional model lighting
5528                 mode = SHADERMODE_LIGHTDIRECTION;
5529                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5530                         permutation |= SHADERPERMUTATION_GLOW;
5531                 permutation |= SHADERPERMUTATION_DIFFUSE;
5532                 if (specularscale > 0)
5533                         permutation |= SHADERPERMUTATION_SPECULAR;
5534                 if (r_refdef.fogenabled)
5535                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5536                 if (rsurface.texture->colormapping)
5537                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5538                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5539                 {
5540                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5541                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5542
5543                         if (r_shadow_shadowmapsampler)
5544                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5545                         if (r_shadow_shadowmappcf > 1)
5546                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5547                         else if (r_shadow_shadowmappcf)
5548                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5549                 }
5550                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5551                         permutation |= SHADERPERMUTATION_REFLECTION;
5552                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5553                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5554                 if (rsurface.texture->reflectmasktexture)
5555                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5556                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5557                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5558                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5559         }
5560         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5561         {
5562                 if (r_glsl_offsetmapping.integer)
5563                 {
5564                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5565                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5566                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5567                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5568                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5569                         {
5570                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5571                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5572                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5573                         }
5574                 }
5575                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5576                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5577                 // ambient model lighting
5578                 mode = SHADERMODE_LIGHTDIRECTION;
5579                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5580                         permutation |= SHADERPERMUTATION_GLOW;
5581                 if (r_refdef.fogenabled)
5582                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5583                 if (rsurface.texture->colormapping)
5584                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5585                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5586                 {
5587                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5588                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5589
5590                         if (r_shadow_shadowmapsampler)
5591                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5592                         if (r_shadow_shadowmappcf > 1)
5593                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5594                         else if (r_shadow_shadowmappcf)
5595                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5596                 }
5597                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5598                         permutation |= SHADERPERMUTATION_REFLECTION;
5599                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5600                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5601                 if (rsurface.texture->reflectmasktexture)
5602                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5603                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5604                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5605                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5606         }
5607         else
5608         {
5609                 if (r_glsl_offsetmapping.integer)
5610                 {
5611                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5612                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5613                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5614                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5615                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5616                         {
5617                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5618                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5619                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5620                         }
5621                 }
5622                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5623                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5624                 // lightmapped wall
5625                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5626                         permutation |= SHADERPERMUTATION_GLOW;
5627                 if (r_refdef.fogenabled)
5628                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5629                 if (rsurface.texture->colormapping)
5630                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5631                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5632                 {
5633                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5634                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5635
5636                         if (r_shadow_shadowmapsampler)
5637                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5638                         if (r_shadow_shadowmappcf > 1)
5639                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5640                         else if (r_shadow_shadowmappcf)
5641                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5642                 }
5643                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5644                         permutation |= SHADERPERMUTATION_REFLECTION;
5645                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5646                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5647                 if (rsurface.texture->reflectmasktexture)
5648                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5649                 if (FAKELIGHT_ENABLED)
5650                 {
5651                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5652                         mode = SHADERMODE_FAKELIGHT;
5653                         permutation |= SHADERPERMUTATION_DIFFUSE;
5654                         if (specularscale > 0)
5655                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5656                 }
5657                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5658                 {
5659                         // deluxemapping (light direction texture)
5660                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5661                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5662                         else
5663                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5664                         permutation |= SHADERPERMUTATION_DIFFUSE;
5665                         if (specularscale > 0)
5666                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5667                 }
5668                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5669                 {
5670                         // fake deluxemapping (uniform light direction in tangentspace)
5671                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5672                         permutation |= SHADERPERMUTATION_DIFFUSE;
5673                         if (specularscale > 0)
5674                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5675                 }
5676                 else if (rsurface.uselightmaptexture)
5677                 {
5678                         // ordinary lightmapping (q1bsp, q3bsp)
5679                         mode = SHADERMODE_LIGHTMAP;
5680                 }
5681                 else
5682                 {
5683                         // ordinary vertex coloring (q3bsp)
5684                         mode = SHADERMODE_VERTEXCOLOR;
5685                 }
5686                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5687                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5688                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5689         }
5690         if(!allow_colormod)
5691                 colormod = dummy_colormod;
5692         switch(vid.renderpath)
5693         {
5694         case RENDERPATH_D3D9:
5695 #ifdef SUPPORTD3D
5696                 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);
5697                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5698                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5699                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5700                 if (mode == SHADERMODE_LIGHTSOURCE)
5701                 {
5702                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5703                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5704                 }
5705                 else
5706                 {
5707                         if (mode == SHADERMODE_LIGHTDIRECTION)
5708                         {
5709                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5710                         }
5711                 }
5712                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5713                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5714                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5715                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5716                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5717
5718                 if (mode == SHADERMODE_LIGHTSOURCE)
5719                 {
5720                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5721                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5722                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5723                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5724                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5725
5726                         // additive passes are only darkened by fog, not tinted
5727                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5728                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5729                 }
5730                 else
5731                 {
5732                         if (mode == SHADERMODE_FLATCOLOR)
5733                         {
5734                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5735                         }
5736                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5737                         {
5738                                 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]);
5739                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5740                                 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);
5741                                 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);
5742                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5743                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5744                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5745                         }
5746                         else
5747                         {
5748                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5749                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5750                                 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);
5751                                 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);
5752                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5753                         }
5754                         // additive passes are only darkened by fog, not tinted
5755                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5756                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5757                         else
5758                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5759                         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);
5760                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5761                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5762                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5763                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5764                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5765                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5766                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5767                         if (mode == SHADERMODE_WATER)
5768                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5769                 }
5770                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5771                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5772                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5773                 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));
5774                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5775                 if (rsurface.texture->pantstexture)
5776                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5777                 else
5778                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5779                 if (rsurface.texture->shirttexture)
5780                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5781                 else
5782                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5783                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5784                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5785                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5786                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5787                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5788                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5789                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5790
5791                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5792                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5793                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5794                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5795                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5796                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5797                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5798                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5799                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5800                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5801                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5802                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5803                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5804                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5805                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5806                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5807                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5808                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5809                 {
5810                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5811                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5812                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5813                 }
5814                 else
5815                 {
5816                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5817                 }
5818 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5819 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5820                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5821                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5822                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5823                 {
5824                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5825                         if (rsurface.rtlight)
5826                         {
5827                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5828                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5829                         }
5830                 }
5831 #endif
5832                 break;
5833         case RENDERPATH_D3D10:
5834                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5835                 break;
5836         case RENDERPATH_D3D11:
5837                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5838                 break;
5839         case RENDERPATH_GL20:
5840                 if (!vid.useinterleavedarrays)
5841                 {
5842                         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);
5843                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5844                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5845                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5846                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5847                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5848                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5849                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5850                 }
5851                 else
5852                 {
5853                         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);
5854                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5855                 }
5856                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5857                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5858                 if (mode == SHADERMODE_LIGHTSOURCE)
5859                 {
5860                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5861                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5862                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5863                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5864                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5865                         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);
5866         
5867                         // additive passes are only darkened by fog, not tinted
5868                         if (r_glsl_permutation->loc_FogColor >= 0)
5869                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5870                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5871                 }
5872                 else
5873                 {
5874                         if (mode == SHADERMODE_FLATCOLOR)
5875                         {
5876                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5877                         }
5878                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5879                         {
5880                                 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]);
5881                                 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]);
5882                                 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);
5883                                 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);
5884                                 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);
5885                                 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]);
5886                                 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]);
5887                         }
5888                         else
5889                         {
5890                                 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]);
5891                                 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]);
5892                                 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);
5893                                 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);
5894                                 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);
5895                         }
5896                         // additive passes are only darkened by fog, not tinted
5897                         if (r_glsl_permutation->loc_FogColor >= 0)
5898                         {
5899                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5900                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5901                                 else
5902                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5903                         }
5904                         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);
5905                         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]);
5906                         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]);
5907                         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]);
5908                         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]);
5909                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5910                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5911                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5912                         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]);
5913                 }
5914                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5915                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5916                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5917                 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]);
5918                 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]);
5919
5920                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5921                 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));
5922                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5923                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5924                 {
5925                         if (rsurface.texture->pantstexture)
5926                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5927                         else
5928                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5929                 }
5930                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5931                 {
5932                         if (rsurface.texture->shirttexture)
5933                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5934                         else
5935                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5936                 }
5937                 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]);
5938                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5939                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5940                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5941                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5942                 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]);
5943                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5944
5945         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5946         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5947         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5948                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5949                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5950                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5951                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5952                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5953                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5954                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5955                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5956                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5957                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5958                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5959                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5960                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5961                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5962                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5963                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5964                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5965                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5966                 {
5967                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5968                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5969                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5970                 }
5971                 else
5972                 {
5973                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5974                 }
5975 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5976 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5977                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5978                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5979                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5980                 {
5981                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5982                         if (rsurface.rtlight)
5983                         {
5984                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5985                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5986                         }
5987                 }
5988                 CHECKGLERROR
5989                 break;
5990         case RENDERPATH_CGGL:
5991 #ifdef SUPPORTCG
5992                 if (!vid.useinterleavedarrays)
5993                 {
5994                         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);
5995                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5996                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5997                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5998                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5999                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6000                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6001                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6002                 }
6003                 else
6004                 {
6005                         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);
6006                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6007                 }
6008                 R_SetupShader_SetPermutationCG(mode, permutation);
6009                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6010                 if (mode == SHADERMODE_LIGHTSOURCE)
6011                 {
6012                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6013                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6014                 }
6015                 else
6016                 {
6017                         if (mode == SHADERMODE_LIGHTDIRECTION)
6018                         {
6019                                 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
6020                         }
6021                 }
6022                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6023                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6024                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6025                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6026                 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
6027                 CHECKGLERROR
6028
6029                 if (mode == SHADERMODE_LIGHTSOURCE)
6030                 {
6031                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6032                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6033                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6034                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6035                         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
6036
6037                         // additive passes are only darkened by fog, not tinted
6038                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6039                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6040                 }
6041                 else
6042                 {
6043                         if (mode == SHADERMODE_FLATCOLOR)
6044                         {
6045                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6046                         }
6047                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6048                         {
6049                                 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
6050                                 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
6051                                 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
6052                                 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
6053                                 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
6054                                 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
6055                                 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
6056                         }
6057                         else
6058                         {
6059                                 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
6060                                 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
6061                                 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
6062                                 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
6063                                 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
6064                         }
6065                         // additive passes are only darkened by fog, not tinted
6066                         if (r_cg_permutation->fp_FogColor)
6067                         {
6068                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6069                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6070                                 else
6071                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6072                                 CHECKCGERROR
6073                         }
6074                         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
6075                         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
6076                         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
6077                         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
6078                         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
6079                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6080                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6081                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6082                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6083                 }
6084                 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
6085                 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
6086                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6087                 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
6088                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6089                 if (r_cg_permutation->fp_Color_Pants)
6090                 {
6091                         if (rsurface.texture->pantstexture)
6092                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6093                         else
6094                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6095                         CHECKCGERROR
6096                 }
6097                 if (r_cg_permutation->fp_Color_Shirt)
6098                 {
6099                         if (rsurface.texture->shirttexture)
6100                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6101                         else
6102                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6103                         CHECKCGERROR
6104                 }
6105                 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
6106                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6107                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6108                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6109                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6110                 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
6111                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6112
6113         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6114         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6115         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6116                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6117                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6118                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6119                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6120                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6121                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6122                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6123                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6124                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6125                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6126                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6127                 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
6128                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6129                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6130                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6131                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6132                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6133                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6134                 {
6135                         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
6136                         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
6137                         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
6138                 }
6139                 else
6140                 {
6141                         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
6142                 }
6143                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6144                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6145                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6146                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6147                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6148                 {
6149                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6150                         if (rsurface.rtlight)
6151                         {
6152                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6153                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6154                         }
6155                 }
6156
6157                 CHECKGLERROR
6158 #endif
6159                 break;
6160         case RENDERPATH_GL13:
6161         case RENDERPATH_GL11:
6162                 break;
6163         case RENDERPATH_SOFT:
6164                 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);
6165                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
6166                 R_SetupShader_SetPermutationSoft(mode, permutation);
6167                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
6168                 if (mode == SHADERMODE_LIGHTSOURCE)
6169                 {
6170                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
6171                         DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
6172                         DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
6173                         DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
6174                         DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
6175                         DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
6176         
6177                         // additive passes are only darkened by fog, not tinted
6178                         DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6179                         DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6180                 }
6181                 else
6182                 {
6183                         if (mode == SHADERMODE_FLATCOLOR)
6184                         {
6185                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
6186                         }
6187                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6188                         {
6189                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_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]);
6190                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
6191                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_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);
6192                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
6193                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6194                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_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]);
6195                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
6196                         }
6197                         else
6198                         {
6199                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
6200                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
6201                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_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);
6202                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_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);
6203                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6204                         }
6205                         // additive passes are only darkened by fog, not tinted
6206                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6207                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6208                         else
6209                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6210                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_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);
6211                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
6212                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
6213                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
6214                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
6215                         DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
6216                         DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
6217                         DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6218                         DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6219                 }
6220                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
6221                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
6222                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
6223                 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6224                 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6225
6226                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
6227                 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
6228                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
6229                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
6230                 {
6231                         if (rsurface.texture->pantstexture)
6232                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6233                         else
6234                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
6235                 }
6236                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
6237                 {
6238                         if (rsurface.texture->shirttexture)
6239                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6240                         else
6241                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
6242                 }
6243                 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
6244                 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
6245                 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
6246                 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
6247                 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6248                 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6249                 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6250
6251         //      R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
6252         //      R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
6253         //      R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
6254                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
6255                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
6256                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
6257                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
6258                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
6259                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
6260                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
6261                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
6262                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
6263                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
6264                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
6265                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6266                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
6267                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
6268                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6269                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6270                 if (rsurface.rtlight                                      ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
6271                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6272                 {
6273                         if(DPSOFTRAST_UNIFORM_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6274                         else if(DPSOFTRAST_UNIFORM_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6275                         if(DPSOFTRAST_UNIFORM_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6276                 }
6277                 else
6278                 {
6279                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6280                 }
6281 //              R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6282 //              R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6283                 R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6284                 R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6285                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6286                 {
6287                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6288                         if (rsurface.rtlight)
6289                         {
6290                                 R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6291                                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6292                         }
6293                 }
6294                 break;
6295         }
6296 }
6297
6298 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6299 {
6300         // select a permutation of the lighting shader appropriate to this
6301         // combination of texture, entity, light source, and fogging, only use the
6302         // minimum features necessary to avoid wasting rendering time in the
6303         // fragment shader on features that are not being used
6304         unsigned int permutation = 0;
6305         unsigned int mode = 0;
6306         const float *lightcolorbase = rtlight->currentcolor;
6307         float ambientscale = rtlight->ambientscale;
6308         float diffusescale = rtlight->diffusescale;
6309         float specularscale = rtlight->specularscale;
6310         // this is the location of the light in view space
6311         vec3_t viewlightorigin;
6312         // this transforms from view space (camera) to light space (cubemap)
6313         matrix4x4_t viewtolight;
6314         matrix4x4_t lighttoview;
6315         float viewtolight16f[16];
6316         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6317         // light source
6318         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6319         if (rtlight->currentcubemap != r_texture_whitecube)
6320                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6321         if (diffusescale > 0)
6322                 permutation |= SHADERPERMUTATION_DIFFUSE;
6323         if (specularscale > 0)
6324                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6325         if (r_shadow_usingshadowmap2d)
6326         {
6327                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6328                 if (r_shadow_shadowmapvsdct)
6329                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6330
6331                 if (r_shadow_shadowmapsampler)
6332                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6333                 if (r_shadow_shadowmappcf > 1)
6334                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6335                 else if (r_shadow_shadowmappcf)
6336                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6337         }
6338         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6339         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6340         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6341         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6342         switch(vid.renderpath)
6343         {
6344         case RENDERPATH_D3D9:
6345 #ifdef SUPPORTD3D
6346                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6347                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6348                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6349                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6350                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6351                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6352                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6353                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6354                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6355                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6356                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6357
6358                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6359                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6360                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6361                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6362                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6363                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6364 #endif
6365                 break;
6366         case RENDERPATH_D3D10:
6367                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6368                 break;
6369         case RENDERPATH_D3D11:
6370                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6371                 break;
6372         case RENDERPATH_GL20:
6373                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6374                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6375                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6376                 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);
6377                 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);
6378                 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);
6379                 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]);
6380                 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]);
6381                 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));
6382                 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]);
6383                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6384
6385                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6386                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6387                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6388                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6389                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6390                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6391                 break;
6392         case RENDERPATH_CGGL:
6393 #ifdef SUPPORTCG
6394                 R_SetupShader_SetPermutationCG(mode, permutation);
6395                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6396                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6397                 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
6398                 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
6399                 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
6400                 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
6401                 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
6402                 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
6403                 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
6404                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6405
6406                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6407                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6408                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6409                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6410                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6411                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6412 #endif
6413                 break;
6414         case RENDERPATH_GL13:
6415         case RENDERPATH_GL11:
6416                 break;
6417         case RENDERPATH_SOFT:
6418                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6419                 DPSOFTRAST_Uniform3fARB(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6420                 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
6421                 DPSOFTRAST_Uniform3fARB(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6422                 DPSOFTRAST_Uniform3fARB(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6423                 DPSOFTRAST_Uniform3fARB(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6424                 DPSOFTRAST_Uniform2fARB(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6425                 DPSOFTRAST_Uniform4fARB(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6426                 DPSOFTRAST_Uniform1fARB(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6427                 DPSOFTRAST_Uniform2fARB(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6428                 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6429
6430                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6431                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6432                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6433                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6434                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6435                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6436                 break;
6437         }
6438 }
6439
6440 #define SKINFRAME_HASH 1024
6441
6442 typedef struct
6443 {
6444         int loadsequence; // incremented each level change
6445         memexpandablearray_t array;
6446         skinframe_t *hash[SKINFRAME_HASH];
6447 }
6448 r_skinframe_t;
6449 r_skinframe_t r_skinframe;
6450
6451 void R_SkinFrame_PrepareForPurge(void)
6452 {
6453         r_skinframe.loadsequence++;
6454         // wrap it without hitting zero
6455         if (r_skinframe.loadsequence >= 200)
6456                 r_skinframe.loadsequence = 1;
6457 }
6458
6459 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6460 {
6461         if (!skinframe)
6462                 return;
6463         // mark the skinframe as used for the purging code
6464         skinframe->loadsequence = r_skinframe.loadsequence;
6465 }
6466
6467 void R_SkinFrame_Purge(void)
6468 {
6469         int i;
6470         skinframe_t *s;
6471         for (i = 0;i < SKINFRAME_HASH;i++)
6472         {
6473                 for (s = r_skinframe.hash[i];s;s = s->next)
6474                 {
6475                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6476                         {
6477                                 if (s->merged == s->base)
6478                                         s->merged = NULL;
6479                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6480                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6481                                 R_PurgeTexture(s->merged);s->merged = NULL;
6482                                 R_PurgeTexture(s->base  );s->base   = NULL;
6483                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6484                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6485                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6486                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6487                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6488                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6489                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6490                                 s->loadsequence = 0;
6491                         }
6492                 }
6493         }
6494 }
6495
6496 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6497         skinframe_t *item;
6498         char basename[MAX_QPATH];
6499
6500         Image_StripImageExtension(name, basename, sizeof(basename));
6501
6502         if( last == NULL ) {
6503                 int hashindex;
6504                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6505                 item = r_skinframe.hash[hashindex];
6506         } else {
6507                 item = last->next;
6508         }
6509
6510         // linearly search through the hash bucket
6511         for( ; item ; item = item->next ) {
6512                 if( !strcmp( item->basename, basename ) ) {
6513                         return item;
6514                 }
6515         }
6516         return NULL;
6517 }
6518
6519 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6520 {
6521         skinframe_t *item;
6522         int hashindex;
6523         char basename[MAX_QPATH];
6524
6525         Image_StripImageExtension(name, basename, sizeof(basename));
6526
6527         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6528         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6529                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6530                         break;
6531
6532         if (!item) {
6533                 rtexture_t *dyntexture;
6534                 // check whether its a dynamic texture
6535                 dyntexture = CL_GetDynTexture( basename );
6536                 if (!add && !dyntexture)
6537                         return NULL;
6538                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6539                 memset(item, 0, sizeof(*item));
6540                 strlcpy(item->basename, basename, sizeof(item->basename));
6541                 item->base = dyntexture; // either NULL or dyntexture handle
6542                 item->textureflags = textureflags;
6543                 item->comparewidth = comparewidth;
6544                 item->compareheight = compareheight;
6545                 item->comparecrc = comparecrc;
6546                 item->next = r_skinframe.hash[hashindex];
6547                 r_skinframe.hash[hashindex] = item;
6548         }
6549         else if( item->base == NULL )
6550         {
6551                 rtexture_t *dyntexture;
6552                 // check whether its a dynamic texture
6553                 // 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]
6554                 dyntexture = CL_GetDynTexture( basename );
6555                 item->base = dyntexture; // either NULL or dyntexture handle
6556         }
6557
6558         R_SkinFrame_MarkUsed(item);
6559         return item;
6560 }
6561
6562 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6563         { \
6564                 unsigned long long avgcolor[5], wsum; \
6565                 int pix, comp, w; \
6566                 avgcolor[0] = 0; \
6567                 avgcolor[1] = 0; \
6568                 avgcolor[2] = 0; \
6569                 avgcolor[3] = 0; \
6570                 avgcolor[4] = 0; \
6571                 wsum = 0; \
6572                 for(pix = 0; pix < cnt; ++pix) \
6573                 { \
6574                         w = 0; \
6575                         for(comp = 0; comp < 3; ++comp) \
6576                                 w += getpixel; \
6577                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6578                         { \
6579                                 ++wsum; \
6580                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6581                                 w = getpixel; \
6582                                 for(comp = 0; comp < 3; ++comp) \
6583                                         avgcolor[comp] += getpixel * w; \
6584                                 avgcolor[3] += w; \
6585                         } \
6586                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6587                         avgcolor[4] += getpixel; \
6588                 } \
6589                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6590                         avgcolor[3] = 1; \
6591                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6592                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6593                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6594                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6595         }
6596
6597 extern cvar_t gl_picmip;
6598 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6599 {
6600         int j;
6601         unsigned char *pixels;
6602         unsigned char *bumppixels;
6603         unsigned char *basepixels = NULL;
6604         int basepixels_width = 0;
6605         int basepixels_height = 0;
6606         skinframe_t *skinframe;
6607         rtexture_t *ddsbase = NULL;
6608         qboolean ddshasalpha = false;
6609         float ddsavgcolor[4];
6610         char basename[MAX_QPATH];
6611         int miplevel = R_PicmipForFlags(textureflags);
6612         int savemiplevel = miplevel;
6613         int mymiplevel;
6614
6615         if (cls.state == ca_dedicated)
6616                 return NULL;
6617
6618         // return an existing skinframe if already loaded
6619         // if loading of the first image fails, don't make a new skinframe as it
6620         // would cause all future lookups of this to be missing
6621         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6622         if (skinframe && skinframe->base)
6623                 return skinframe;
6624
6625         Image_StripImageExtension(name, basename, sizeof(basename));
6626
6627         // check for DDS texture file first
6628         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6629         {
6630                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6631                 if (basepixels == NULL)
6632                         return NULL;
6633         }
6634
6635         // FIXME handle miplevel
6636
6637         if (developer_loading.integer)
6638                 Con_Printf("loading skin \"%s\"\n", name);
6639
6640         // we've got some pixels to store, so really allocate this new texture now
6641         if (!skinframe)
6642                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6643         skinframe->stain = NULL;
6644         skinframe->merged = NULL;
6645         skinframe->base = NULL;
6646         skinframe->pants = NULL;
6647         skinframe->shirt = NULL;
6648         skinframe->nmap = NULL;
6649         skinframe->gloss = NULL;
6650         skinframe->glow = NULL;
6651         skinframe->fog = NULL;
6652         skinframe->reflect = NULL;
6653         skinframe->hasalpha = false;
6654
6655         if (ddsbase)
6656         {
6657                 skinframe->base = ddsbase;
6658                 skinframe->hasalpha = ddshasalpha;
6659                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6660                 if (r_loadfog && skinframe->hasalpha)
6661                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6662                 //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]);
6663         }
6664         else
6665         {
6666                 basepixels_width = image_width;
6667                 basepixels_height = image_height;
6668                 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);
6669                 if (textureflags & TEXF_ALPHA)
6670                 {
6671                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6672                         {
6673                                 if (basepixels[j] < 255)
6674                                 {
6675                                         skinframe->hasalpha = true;
6676                                         break;
6677                                 }
6678                         }
6679                         if (r_loadfog && skinframe->hasalpha)
6680                         {
6681                                 // has transparent pixels
6682                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6683                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6684                                 {
6685                                         pixels[j+0] = 255;
6686                                         pixels[j+1] = 255;
6687                                         pixels[j+2] = 255;
6688                                         pixels[j+3] = basepixels[j+3];
6689                                 }
6690                                 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);
6691                                 Mem_Free(pixels);
6692                         }
6693                 }
6694                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6695                 //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]);
6696                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6697                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6698                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6699                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6700         }
6701
6702         if (r_loaddds)
6703         {
6704                 mymiplevel = savemiplevel;
6705                 if (r_loadnormalmap)
6706                         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);
6707                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6708                 if (r_loadgloss)
6709                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6710                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6711                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6712                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6713         }
6714
6715         // _norm is the name used by tenebrae and has been adopted as standard
6716         if (r_loadnormalmap && skinframe->nmap == NULL)
6717         {
6718                 mymiplevel = savemiplevel;
6719                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6720                 {
6721                         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);
6722                         Mem_Free(pixels);
6723                         pixels = NULL;
6724                 }
6725                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6726                 {
6727                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6728                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6729                         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);
6730                         Mem_Free(pixels);
6731                         Mem_Free(bumppixels);
6732                 }
6733                 else if (r_shadow_bumpscale_basetexture.value > 0)
6734                 {
6735                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6736                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6737                         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);
6738                         Mem_Free(pixels);
6739                 }
6740                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6741                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6742         }
6743
6744         // _luma is supported only for tenebrae compatibility
6745         // _glow is the preferred name
6746         mymiplevel = savemiplevel;
6747         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))))
6748         {
6749                 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);
6750                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6751                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6752                 Mem_Free(pixels);pixels = NULL;
6753         }
6754
6755         mymiplevel = savemiplevel;
6756         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6757         {
6758                 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);
6759                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6760                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6761                 Mem_Free(pixels);
6762                 pixels = NULL;
6763         }
6764
6765         mymiplevel = savemiplevel;
6766         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6767         {
6768                 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);
6769                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6770                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6771                 Mem_Free(pixels);
6772                 pixels = NULL;
6773         }
6774
6775         mymiplevel = savemiplevel;
6776         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6777         {
6778                 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);
6779                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6780                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6781                 Mem_Free(pixels);
6782                 pixels = NULL;
6783         }
6784
6785         mymiplevel = savemiplevel;
6786         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6787         {
6788                 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);
6789                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6790                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6791                 Mem_Free(pixels);
6792                 pixels = NULL;
6793         }
6794
6795         if (basepixels)
6796                 Mem_Free(basepixels);
6797
6798         return skinframe;
6799 }
6800
6801 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6802 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6803 {
6804         int i;
6805         unsigned char *temp1, *temp2;
6806         skinframe_t *skinframe;
6807
6808         if (cls.state == ca_dedicated)
6809                 return NULL;
6810
6811         // if already loaded just return it, otherwise make a new skinframe
6812         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6813         if (skinframe && skinframe->base)
6814                 return skinframe;
6815
6816         skinframe->stain = NULL;
6817         skinframe->merged = NULL;
6818         skinframe->base = NULL;
6819         skinframe->pants = NULL;
6820         skinframe->shirt = NULL;
6821         skinframe->nmap = NULL;
6822         skinframe->gloss = NULL;
6823         skinframe->glow = NULL;
6824         skinframe->fog = NULL;
6825         skinframe->reflect = NULL;
6826         skinframe->hasalpha = false;
6827
6828         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6829         if (!skindata)
6830                 return NULL;
6831
6832         if (developer_loading.integer)
6833                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6834
6835         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6836         {
6837                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6838                 temp2 = temp1 + width * height * 4;
6839                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6840                 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);
6841                 Mem_Free(temp1);
6842         }
6843         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6844         if (textureflags & TEXF_ALPHA)
6845         {
6846                 for (i = 3;i < width * height * 4;i += 4)
6847                 {
6848                         if (skindata[i] < 255)
6849                         {
6850                                 skinframe->hasalpha = true;
6851                                 break;
6852                         }
6853                 }
6854                 if (r_loadfog && skinframe->hasalpha)
6855                 {
6856                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6857                         memcpy(fogpixels, skindata, width * height * 4);
6858                         for (i = 0;i < width * height * 4;i += 4)
6859                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6860                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6861                         Mem_Free(fogpixels);
6862                 }
6863         }
6864
6865         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6866         //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]);
6867
6868         return skinframe;
6869 }
6870
6871 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6872 {
6873         int i;
6874         int featuresmask;
6875         skinframe_t *skinframe;
6876
6877         if (cls.state == ca_dedicated)
6878                 return NULL;
6879
6880         // if already loaded just return it, otherwise make a new skinframe
6881         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6882         if (skinframe && skinframe->base)
6883                 return skinframe;
6884
6885         skinframe->stain = NULL;
6886         skinframe->merged = NULL;
6887         skinframe->base = NULL;
6888         skinframe->pants = NULL;
6889         skinframe->shirt = NULL;
6890         skinframe->nmap = NULL;
6891         skinframe->gloss = NULL;
6892         skinframe->glow = NULL;
6893         skinframe->fog = NULL;
6894         skinframe->reflect = NULL;
6895         skinframe->hasalpha = false;
6896
6897         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6898         if (!skindata)
6899                 return NULL;
6900
6901         if (developer_loading.integer)
6902                 Con_Printf("loading quake skin \"%s\"\n", name);
6903
6904         // 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)
6905         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6906         memcpy(skinframe->qpixels, skindata, width*height);
6907         skinframe->qwidth = width;
6908         skinframe->qheight = height;
6909
6910         featuresmask = 0;
6911         for (i = 0;i < width * height;i++)
6912                 featuresmask |= palette_featureflags[skindata[i]];
6913
6914         skinframe->hasalpha = false;
6915         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6916         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6917         skinframe->qgeneratemerged = true;
6918         skinframe->qgeneratebase = skinframe->qhascolormapping;
6919         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6920
6921         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6922         //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]);
6923
6924         return skinframe;
6925 }
6926
6927 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6928 {
6929         int width;
6930         int height;
6931         unsigned char *skindata;
6932
6933         if (!skinframe->qpixels)
6934                 return;
6935
6936         if (!skinframe->qhascolormapping)
6937                 colormapped = false;
6938
6939         if (colormapped)
6940         {
6941                 if (!skinframe->qgeneratebase)
6942                         return;
6943         }
6944         else
6945         {
6946                 if (!skinframe->qgeneratemerged)
6947                         return;
6948         }
6949
6950         width = skinframe->qwidth;
6951         height = skinframe->qheight;
6952         skindata = skinframe->qpixels;
6953
6954         if (skinframe->qgeneratenmap)
6955         {
6956                 unsigned char *temp1, *temp2;
6957                 skinframe->qgeneratenmap = false;
6958                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6959                 temp2 = temp1 + width * height * 4;
6960                 // use either a custom palette or the quake palette
6961                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6962                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6963                 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);
6964                 Mem_Free(temp1);
6965         }
6966
6967         if (skinframe->qgenerateglow)
6968         {
6969                 skinframe->qgenerateglow = false;
6970                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6971         }
6972
6973         if (colormapped)
6974         {
6975                 skinframe->qgeneratebase = false;
6976                 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);
6977                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6978                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6979         }
6980         else
6981         {
6982                 skinframe->qgeneratemerged = false;
6983                 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);
6984         }
6985
6986         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6987         {
6988                 Mem_Free(skinframe->qpixels);
6989                 skinframe->qpixels = NULL;
6990         }
6991 }
6992
6993 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)
6994 {
6995         int i;
6996         skinframe_t *skinframe;
6997
6998         if (cls.state == ca_dedicated)
6999                 return NULL;
7000
7001         // if already loaded just return it, otherwise make a new skinframe
7002         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
7003         if (skinframe && skinframe->base)
7004                 return skinframe;
7005
7006         skinframe->stain = NULL;
7007         skinframe->merged = NULL;
7008         skinframe->base = NULL;
7009         skinframe->pants = NULL;
7010         skinframe->shirt = NULL;
7011         skinframe->nmap = NULL;
7012         skinframe->gloss = NULL;
7013         skinframe->glow = NULL;
7014         skinframe->fog = NULL;
7015         skinframe->reflect = NULL;
7016         skinframe->hasalpha = false;
7017
7018         // if no data was provided, then clearly the caller wanted to get a blank skinframe
7019         if (!skindata)
7020                 return NULL;
7021
7022         if (developer_loading.integer)
7023                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
7024
7025         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
7026         if (textureflags & TEXF_ALPHA)
7027         {
7028                 for (i = 0;i < width * height;i++)
7029                 {
7030                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
7031                         {
7032                                 skinframe->hasalpha = true;
7033                                 break;
7034                         }
7035                 }
7036                 if (r_loadfog && skinframe->hasalpha)
7037                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
7038         }
7039
7040         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
7041         //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]);
7042
7043         return skinframe;
7044 }
7045
7046 skinframe_t *R_SkinFrame_LoadMissing(void)
7047 {
7048         skinframe_t *skinframe;
7049
7050         if (cls.state == ca_dedicated)
7051                 return NULL;
7052
7053         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
7054         skinframe->stain = NULL;
7055         skinframe->merged = NULL;
7056         skinframe->base = NULL;
7057         skinframe->pants = NULL;
7058         skinframe->shirt = NULL;
7059         skinframe->nmap = NULL;
7060         skinframe->gloss = NULL;
7061         skinframe->glow = NULL;
7062         skinframe->fog = NULL;
7063         skinframe->reflect = NULL;
7064         skinframe->hasalpha = false;
7065
7066         skinframe->avgcolor[0] = rand() / RAND_MAX;
7067         skinframe->avgcolor[1] = rand() / RAND_MAX;
7068         skinframe->avgcolor[2] = rand() / RAND_MAX;
7069         skinframe->avgcolor[3] = 1;
7070
7071         return skinframe;
7072 }
7073
7074 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7075 typedef struct suffixinfo_s
7076 {
7077         const char *suffix;
7078         qboolean flipx, flipy, flipdiagonal;
7079 }
7080 suffixinfo_t;
7081 static suffixinfo_t suffix[3][6] =
7082 {
7083         {
7084                 {"px",   false, false, false},
7085                 {"nx",   false, false, false},
7086                 {"py",   false, false, false},
7087                 {"ny",   false, false, false},
7088                 {"pz",   false, false, false},
7089                 {"nz",   false, false, false}
7090         },
7091         {
7092                 {"posx", false, false, false},
7093                 {"negx", false, false, false},
7094                 {"posy", false, false, false},
7095                 {"negy", false, false, false},
7096                 {"posz", false, false, false},
7097                 {"negz", false, false, false}
7098         },
7099         {
7100                 {"rt",    true, false,  true},
7101                 {"lf",   false,  true,  true},
7102                 {"ft",    true,  true, false},
7103                 {"bk",   false, false, false},
7104                 {"up",    true, false,  true},
7105                 {"dn",    true, false,  true}
7106         }
7107 };
7108
7109 static int componentorder[4] = {0, 1, 2, 3};
7110
7111 rtexture_t *R_LoadCubemap(const char *basename)
7112 {
7113         int i, j, cubemapsize;
7114         unsigned char *cubemappixels, *image_buffer;
7115         rtexture_t *cubemaptexture;
7116         char name[256];
7117         // must start 0 so the first loadimagepixels has no requested width/height
7118         cubemapsize = 0;
7119         cubemappixels = NULL;
7120         cubemaptexture = NULL;
7121         // keep trying different suffix groups (posx, px, rt) until one loads
7122         for (j = 0;j < 3 && !cubemappixels;j++)
7123         {
7124                 // load the 6 images in the suffix group
7125                 for (i = 0;i < 6;i++)
7126                 {
7127                         // generate an image name based on the base and and suffix
7128                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7129                         // load it
7130                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7131                         {
7132                                 // an image loaded, make sure width and height are equal
7133                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7134                                 {
7135                                         // if this is the first image to load successfully, allocate the cubemap memory
7136                                         if (!cubemappixels && image_width >= 1)
7137                                         {
7138                                                 cubemapsize = image_width;
7139                                                 // note this clears to black, so unavailable sides are black
7140                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7141                                         }
7142                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7143                                         if (cubemappixels)
7144                                                 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);
7145                                 }
7146                                 else
7147                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7148                                 // free the image
7149                                 Mem_Free(image_buffer);
7150                         }
7151                 }
7152         }
7153         // if a cubemap loaded, upload it
7154         if (cubemappixels)
7155         {
7156                 if (developer_loading.integer)
7157                         Con_Printf("loading cubemap \"%s\"\n", basename);
7158
7159                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7160                 Mem_Free(cubemappixels);
7161         }
7162         else
7163         {
7164                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7165                 if (developer_loading.integer)
7166                 {
7167                         Con_Printf("(tried tried images ");
7168                         for (j = 0;j < 3;j++)
7169                                 for (i = 0;i < 6;i++)
7170                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7171                         Con_Print(" and was unable to find any of them).\n");
7172                 }
7173         }
7174         return cubemaptexture;
7175 }
7176
7177 rtexture_t *R_GetCubemap(const char *basename)
7178 {
7179         int i;
7180         for (i = 0;i < r_texture_numcubemaps;i++)
7181                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7182                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7183         if (i >= MAX_CUBEMAPS)
7184                 return r_texture_whitecube;
7185         r_texture_numcubemaps++;
7186         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7187         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7188         return r_texture_cubemaps[i].texture;
7189 }
7190
7191 void R_FreeCubemaps(void)
7192 {
7193         int i;
7194         for (i = 0;i < r_texture_numcubemaps;i++)
7195         {
7196                 if (developer_loading.integer)
7197                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7198                 if (r_texture_cubemaps[i].texture)
7199                         R_FreeTexture(r_texture_cubemaps[i].texture);
7200         }
7201         r_texture_numcubemaps = 0;
7202 }
7203
7204 void R_Main_FreeViewCache(void)
7205 {
7206         if (r_refdef.viewcache.entityvisible)
7207                 Mem_Free(r_refdef.viewcache.entityvisible);
7208         if (r_refdef.viewcache.world_pvsbits)
7209                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7210         if (r_refdef.viewcache.world_leafvisible)
7211                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7212         if (r_refdef.viewcache.world_surfacevisible)
7213                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7214         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7215 }
7216
7217 void R_Main_ResizeViewCache(void)
7218 {
7219         int numentities = r_refdef.scene.numentities;
7220         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7221         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7222         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7223         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7224         if (r_refdef.viewcache.maxentities < numentities)
7225         {
7226                 r_refdef.viewcache.maxentities = numentities;
7227                 if (r_refdef.viewcache.entityvisible)
7228                         Mem_Free(r_refdef.viewcache.entityvisible);
7229                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7230         }
7231         if (r_refdef.viewcache.world_numclusters != numclusters)
7232         {
7233                 r_refdef.viewcache.world_numclusters = numclusters;
7234                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7235                 if (r_refdef.viewcache.world_pvsbits)
7236                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7237                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7238         }
7239         if (r_refdef.viewcache.world_numleafs != numleafs)
7240         {
7241                 r_refdef.viewcache.world_numleafs = numleafs;
7242                 if (r_refdef.viewcache.world_leafvisible)
7243                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7244                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7245         }
7246         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7247         {
7248                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7249                 if (r_refdef.viewcache.world_surfacevisible)
7250                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7251                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7252         }
7253 }
7254
7255 extern rtexture_t *loadingscreentexture;
7256 void gl_main_start(void)
7257 {
7258         loadingscreentexture = NULL;
7259         r_texture_blanknormalmap = NULL;
7260         r_texture_white = NULL;
7261         r_texture_grey128 = NULL;
7262         r_texture_black = NULL;
7263         r_texture_whitecube = NULL;
7264         r_texture_normalizationcube = NULL;
7265         r_texture_fogattenuation = NULL;
7266         r_texture_fogheighttexture = NULL;
7267         r_texture_gammaramps = NULL;
7268         r_texture_numcubemaps = 0;
7269
7270         r_loaddds = r_texture_dds_load.integer != 0;
7271         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7272
7273         switch(vid.renderpath)
7274         {
7275         case RENDERPATH_GL20:
7276         case RENDERPATH_CGGL:
7277         case RENDERPATH_D3D9:
7278         case RENDERPATH_D3D10:
7279         case RENDERPATH_D3D11:
7280         case RENDERPATH_SOFT:
7281                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7282                 Cvar_SetValueQuick(&gl_combine, 1);
7283                 Cvar_SetValueQuick(&r_glsl, 1);
7284                 r_loadnormalmap = true;
7285                 r_loadgloss = true;
7286                 r_loadfog = false;
7287                 break;
7288         case RENDERPATH_GL13:
7289                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7290                 Cvar_SetValueQuick(&gl_combine, 1);
7291                 Cvar_SetValueQuick(&r_glsl, 0);
7292                 r_loadnormalmap = false;
7293                 r_loadgloss = false;
7294                 r_loadfog = true;
7295                 break;
7296         case RENDERPATH_GL11:
7297                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7298                 Cvar_SetValueQuick(&gl_combine, 0);
7299                 Cvar_SetValueQuick(&r_glsl, 0);
7300                 r_loadnormalmap = false;
7301                 r_loadgloss = false;
7302                 r_loadfog = true;
7303                 break;
7304         }
7305
7306         R_AnimCache_Free();
7307         R_FrameData_Reset();
7308
7309         r_numqueries = 0;
7310         r_maxqueries = 0;
7311         memset(r_queries, 0, sizeof(r_queries));
7312
7313         r_qwskincache = NULL;
7314         r_qwskincache_size = 0;
7315
7316         // set up r_skinframe loading system for textures
7317         memset(&r_skinframe, 0, sizeof(r_skinframe));
7318         r_skinframe.loadsequence = 1;
7319         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7320
7321         r_main_texturepool = R_AllocTexturePool();
7322         R_BuildBlankTextures();
7323         R_BuildNoTexture();
7324         if (vid.support.arb_texture_cube_map)
7325         {
7326                 R_BuildWhiteCube();
7327                 R_BuildNormalizationCube();
7328         }
7329         r_texture_fogattenuation = NULL;
7330         r_texture_fogheighttexture = NULL;
7331         r_texture_gammaramps = NULL;
7332         //r_texture_fogintensity = NULL;
7333         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7334         memset(&r_waterstate, 0, sizeof(r_waterstate));
7335         r_glsl_permutation = NULL;
7336         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7337         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7338         glslshaderstring = NULL;
7339 #ifdef SUPPORTCG
7340         r_cg_permutation = NULL;
7341         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7342         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7343         cgshaderstring = NULL;
7344 #endif
7345 #ifdef SUPPORTD3D
7346         r_hlsl_permutation = NULL;
7347         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7348         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7349         hlslshaderstring = NULL;
7350 #endif
7351         memset(&r_svbsp, 0, sizeof (r_svbsp));
7352
7353         r_refdef.fogmasktable_density = 0;
7354 }
7355
7356 void gl_main_shutdown(void)
7357 {
7358         R_AnimCache_Free();
7359         R_FrameData_Reset();
7360
7361         R_Main_FreeViewCache();
7362
7363         switch(vid.renderpath)
7364         {
7365         case RENDERPATH_GL11:
7366         case RENDERPATH_GL13:
7367         case RENDERPATH_GL20:
7368         case RENDERPATH_CGGL:
7369                 if (r_maxqueries)
7370                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7371                 break;
7372         case RENDERPATH_D3D9:
7373                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7374                 break;
7375         case RENDERPATH_D3D10:
7376                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7377                 break;
7378         case RENDERPATH_D3D11:
7379                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7380                 break;
7381         case RENDERPATH_SOFT:
7382                 break;
7383         }
7384
7385         r_numqueries = 0;
7386         r_maxqueries = 0;
7387         memset(r_queries, 0, sizeof(r_queries));
7388
7389         r_qwskincache = NULL;
7390         r_qwskincache_size = 0;
7391
7392         // clear out the r_skinframe state
7393         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7394         memset(&r_skinframe, 0, sizeof(r_skinframe));
7395
7396         if (r_svbsp.nodes)
7397                 Mem_Free(r_svbsp.nodes);
7398         memset(&r_svbsp, 0, sizeof (r_svbsp));
7399         R_FreeTexturePool(&r_main_texturepool);
7400         loadingscreentexture = NULL;
7401         r_texture_blanknormalmap = NULL;
7402         r_texture_white = NULL;
7403         r_texture_grey128 = NULL;
7404         r_texture_black = NULL;
7405         r_texture_whitecube = NULL;
7406         r_texture_normalizationcube = NULL;
7407         r_texture_fogattenuation = NULL;
7408         r_texture_fogheighttexture = NULL;
7409         r_texture_gammaramps = NULL;
7410         r_texture_numcubemaps = 0;
7411         //r_texture_fogintensity = NULL;
7412         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7413         memset(&r_waterstate, 0, sizeof(r_waterstate));
7414         R_GLSL_Restart_f();
7415
7416         r_glsl_permutation = NULL;
7417         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7418         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7419         glslshaderstring = NULL;
7420 #ifdef SUPPORTCG
7421         r_cg_permutation = NULL;
7422         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7423         Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7424         cgshaderstring = NULL;
7425 #endif
7426 #ifdef SUPPORTD3D
7427         r_hlsl_permutation = NULL;
7428         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7429         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7430         hlslshaderstring = NULL;
7431 #endif
7432 }
7433
7434 extern void CL_ParseEntityLump(char *entitystring);
7435 void gl_main_newmap(void)
7436 {
7437         // FIXME: move this code to client
7438         char *entities, entname[MAX_QPATH];
7439         if (r_qwskincache)
7440                 Mem_Free(r_qwskincache);
7441         r_qwskincache = NULL;
7442         r_qwskincache_size = 0;
7443         if (cl.worldmodel)
7444         {
7445                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7446                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7447                 {
7448                         CL_ParseEntityLump(entities);
7449                         Mem_Free(entities);
7450                         return;
7451                 }
7452                 if (cl.worldmodel->brush.entities)
7453                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7454         }
7455         R_Main_FreeViewCache();
7456
7457         R_FrameData_Reset();
7458 }
7459
7460 void GL_Main_Init(void)
7461 {
7462         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7463
7464         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7465         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7466         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7467         if (gamemode == GAME_NEHAHRA)
7468         {
7469                 Cvar_RegisterVariable (&gl_fogenable);
7470                 Cvar_RegisterVariable (&gl_fogdensity);
7471                 Cvar_RegisterVariable (&gl_fogred);
7472                 Cvar_RegisterVariable (&gl_foggreen);
7473                 Cvar_RegisterVariable (&gl_fogblue);
7474                 Cvar_RegisterVariable (&gl_fogstart);
7475                 Cvar_RegisterVariable (&gl_fogend);
7476                 Cvar_RegisterVariable (&gl_skyclip);
7477         }
7478         Cvar_RegisterVariable(&r_motionblur);
7479         Cvar_RegisterVariable(&r_motionblur_maxblur);
7480         Cvar_RegisterVariable(&r_motionblur_bmin);
7481         Cvar_RegisterVariable(&r_motionblur_vmin);
7482         Cvar_RegisterVariable(&r_motionblur_vmax);
7483         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7484         Cvar_RegisterVariable(&r_motionblur_randomize);
7485         Cvar_RegisterVariable(&r_damageblur);
7486         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7487         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7488         Cvar_RegisterVariable(&r_equalize_entities_by);
7489         Cvar_RegisterVariable(&r_equalize_entities_to);
7490         Cvar_RegisterVariable(&r_depthfirst);
7491         Cvar_RegisterVariable(&r_useinfinitefarclip);
7492         Cvar_RegisterVariable(&r_farclip_base);
7493         Cvar_RegisterVariable(&r_farclip_world);
7494         Cvar_RegisterVariable(&r_nearclip);
7495         Cvar_RegisterVariable(&r_showbboxes);
7496         Cvar_RegisterVariable(&r_showsurfaces);
7497         Cvar_RegisterVariable(&r_showtris);
7498         Cvar_RegisterVariable(&r_shownormals);
7499         Cvar_RegisterVariable(&r_showlighting);
7500         Cvar_RegisterVariable(&r_showshadowvolumes);
7501         Cvar_RegisterVariable(&r_showcollisionbrushes);
7502         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7503         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7504         Cvar_RegisterVariable(&r_showdisabledepthtest);
7505         Cvar_RegisterVariable(&r_drawportals);
7506         Cvar_RegisterVariable(&r_drawentities);
7507         Cvar_RegisterVariable(&r_draw2d);
7508         Cvar_RegisterVariable(&r_drawworld);
7509         Cvar_RegisterVariable(&r_cullentities_trace);
7510         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7511         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7512         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7513         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7514         Cvar_RegisterVariable(&r_drawviewmodel);
7515         Cvar_RegisterVariable(&r_drawexteriormodel);
7516         Cvar_RegisterVariable(&r_speeds);
7517         Cvar_RegisterVariable(&r_fullbrights);
7518         Cvar_RegisterVariable(&r_wateralpha);
7519         Cvar_RegisterVariable(&r_dynamic);
7520         Cvar_RegisterVariable(&r_fakelight);
7521         Cvar_RegisterVariable(&r_fakelight_intensity);
7522         Cvar_RegisterVariable(&r_fullbright);
7523         Cvar_RegisterVariable(&r_shadows);
7524         Cvar_RegisterVariable(&r_shadows_darken);
7525         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7526         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7527         Cvar_RegisterVariable(&r_shadows_throwdistance);
7528         Cvar_RegisterVariable(&r_shadows_throwdirection);
7529         Cvar_RegisterVariable(&r_shadows_focus);
7530         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7531         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7532         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7533         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7534         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7535         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7536         Cvar_RegisterVariable(&r_fog_exp2);
7537         Cvar_RegisterVariable(&r_drawfog);
7538         Cvar_RegisterVariable(&r_transparentdepthmasking);
7539         Cvar_RegisterVariable(&r_texture_dds_load);
7540         Cvar_RegisterVariable(&r_texture_dds_save);
7541         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7542         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7543         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7544         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7545         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7546         Cvar_RegisterVariable(&r_textureunits);
7547         Cvar_RegisterVariable(&gl_combine);
7548         Cvar_RegisterVariable(&r_glsl);
7549         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7550         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7551         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7552         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7553         Cvar_RegisterVariable(&r_glsl_postprocess);
7554         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7555         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7556         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7557         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7558         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7559         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7560         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7561         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7562
7563         Cvar_RegisterVariable(&r_water);
7564         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7565         Cvar_RegisterVariable(&r_water_clippingplanebias);
7566         Cvar_RegisterVariable(&r_water_refractdistort);
7567         Cvar_RegisterVariable(&r_water_reflectdistort);
7568         Cvar_RegisterVariable(&r_water_scissormode);
7569         Cvar_RegisterVariable(&r_lerpsprites);
7570         Cvar_RegisterVariable(&r_lerpmodels);
7571         Cvar_RegisterVariable(&r_lerplightstyles);
7572         Cvar_RegisterVariable(&r_waterscroll);
7573         Cvar_RegisterVariable(&r_bloom);
7574         Cvar_RegisterVariable(&r_bloom_colorscale);
7575         Cvar_RegisterVariable(&r_bloom_brighten);
7576         Cvar_RegisterVariable(&r_bloom_blur);
7577         Cvar_RegisterVariable(&r_bloom_resolution);
7578         Cvar_RegisterVariable(&r_bloom_colorexponent);
7579         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7580         Cvar_RegisterVariable(&r_hdr);
7581         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7582         Cvar_RegisterVariable(&r_hdr_glowintensity);
7583         Cvar_RegisterVariable(&r_hdr_range);
7584         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7585         Cvar_RegisterVariable(&developer_texturelogging);
7586         Cvar_RegisterVariable(&gl_lightmaps);
7587         Cvar_RegisterVariable(&r_test);
7588         Cvar_RegisterVariable(&r_glsl_saturation);
7589         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7590         Cvar_RegisterVariable(&r_framedatasize);
7591         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7592                 Cvar_SetValue("r_fullbrights", 0);
7593         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7594
7595         Cvar_RegisterVariable(&r_track_sprites);
7596         Cvar_RegisterVariable(&r_track_sprites_flags);
7597         Cvar_RegisterVariable(&r_track_sprites_scalew);
7598         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7599         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7600         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7601         Cvar_RegisterVariable(&r_overheadsprites_scalex);
7602         Cvar_RegisterVariable(&r_overheadsprites_scaley);
7603 }
7604
7605 extern void R_Textures_Init(void);
7606 extern void GL_Draw_Init(void);
7607 extern void GL_Main_Init(void);
7608 extern void R_Shadow_Init(void);
7609 extern void R_Sky_Init(void);
7610 extern void GL_Surf_Init(void);
7611 extern void R_Particles_Init(void);
7612 extern void R_Explosion_Init(void);
7613 extern void gl_backend_init(void);
7614 extern void Sbar_Init(void);
7615 extern void R_LightningBeams_Init(void);
7616 extern void Mod_RenderInit(void);
7617 extern void Font_Init(void);
7618
7619 void Render_Init(void)
7620 {
7621         gl_backend_init();
7622         R_Textures_Init();
7623         GL_Main_Init();
7624         Font_Init();
7625         GL_Draw_Init();
7626         R_Shadow_Init();
7627         R_Sky_Init();
7628         GL_Surf_Init();
7629         Sbar_Init();
7630         R_Particles_Init();
7631         R_Explosion_Init();
7632         R_LightningBeams_Init();
7633         Mod_RenderInit();
7634 }
7635
7636 /*
7637 ===============
7638 GL_Init
7639 ===============
7640 */
7641 extern char *ENGINE_EXTENSIONS;
7642 void GL_Init (void)
7643 {
7644         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7645         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7646         gl_version = (const char *)qglGetString(GL_VERSION);
7647         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7648
7649         if (!gl_extensions)
7650                 gl_extensions = "";
7651         if (!gl_platformextensions)
7652                 gl_platformextensions = "";
7653
7654         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7655         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7656         Con_Printf("GL_VERSION: %s\n", gl_version);
7657         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7658         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7659
7660         VID_CheckExtensions();
7661
7662         // LordHavoc: report supported extensions
7663         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7664
7665         // clear to black (loading plaque will be seen over this)
7666         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7667 }
7668
7669 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7670 {
7671         int i;
7672         mplane_t *p;
7673         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7674         {
7675                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7676                 if (i == 4)
7677                         continue;
7678                 p = r_refdef.view.frustum + i;
7679                 switch(p->signbits)
7680                 {
7681                 default:
7682                 case 0:
7683                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7684                                 return true;
7685                         break;
7686                 case 1:
7687                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7688                                 return true;
7689                         break;
7690                 case 2:
7691                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7692                                 return true;
7693                         break;
7694                 case 3:
7695                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7696                                 return true;
7697                         break;
7698                 case 4:
7699                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7700                                 return true;
7701                         break;
7702                 case 5:
7703                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7704                                 return true;
7705                         break;
7706                 case 6:
7707                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7708                                 return true;
7709                         break;
7710                 case 7:
7711                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7712                                 return true;
7713                         break;
7714                 }
7715         }
7716         return false;
7717 }
7718
7719 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7720 {
7721         int i;
7722         const mplane_t *p;
7723         for (i = 0;i < numplanes;i++)
7724         {
7725                 p = planes + i;
7726                 switch(p->signbits)
7727                 {
7728                 default:
7729                 case 0:
7730                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7731                                 return true;
7732                         break;
7733                 case 1:
7734                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7735                                 return true;
7736                         break;
7737                 case 2:
7738                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7739                                 return true;
7740                         break;
7741                 case 3:
7742                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7743                                 return true;
7744                         break;
7745                 case 4:
7746                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7747                                 return true;
7748                         break;
7749                 case 5:
7750                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7751                                 return true;
7752                         break;
7753                 case 6:
7754                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7755                                 return true;
7756                         break;
7757                 case 7:
7758                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7759                                 return true;
7760                         break;
7761                 }
7762         }
7763         return false;
7764 }
7765
7766 //==================================================================================
7767
7768 // LordHavoc: this stores temporary data used within the same frame
7769
7770 typedef struct r_framedata_mem_s
7771 {
7772         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7773         size_t size; // how much usable space
7774         size_t current; // how much space in use
7775         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7776         size_t wantedsize; // how much space was allocated
7777         unsigned char *data; // start of real data (16byte aligned)
7778 }
7779 r_framedata_mem_t;
7780
7781 static r_framedata_mem_t *r_framedata_mem;
7782
7783 void R_FrameData_Reset(void)
7784 {
7785         while (r_framedata_mem)
7786         {
7787                 r_framedata_mem_t *next = r_framedata_mem->purge;
7788                 Mem_Free(r_framedata_mem);
7789                 r_framedata_mem = next;
7790         }
7791 }
7792
7793 void R_FrameData_Resize(void)
7794 {
7795         size_t wantedsize;
7796         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7797         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7798         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7799         {
7800                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7801                 newmem->wantedsize = wantedsize;
7802                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7803                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7804                 newmem->current = 0;
7805                 newmem->mark = 0;
7806                 newmem->purge = r_framedata_mem;
7807                 r_framedata_mem = newmem;
7808         }
7809 }
7810
7811 void R_FrameData_NewFrame(void)
7812 {
7813         R_FrameData_Resize();
7814         if (!r_framedata_mem)
7815                 return;
7816         // if we ran out of space on the last frame, free the old memory now
7817         while (r_framedata_mem->purge)
7818         {
7819                 // repeatedly remove the second item in the list, leaving only head
7820                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7821                 Mem_Free(r_framedata_mem->purge);
7822                 r_framedata_mem->purge = next;
7823         }
7824         // reset the current mem pointer
7825         r_framedata_mem->current = 0;
7826         r_framedata_mem->mark = 0;
7827 }
7828
7829 void *R_FrameData_Alloc(size_t size)
7830 {
7831         void *data;
7832
7833         // align to 16 byte boundary - the data pointer is already aligned, so we
7834         // only need to ensure the size of every allocation is also aligned
7835         size = (size + 15) & ~15;
7836
7837         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7838         {
7839                 // emergency - we ran out of space, allocate more memory
7840                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7841                 R_FrameData_Resize();
7842         }
7843
7844         data = r_framedata_mem->data + r_framedata_mem->current;
7845         r_framedata_mem->current += size;
7846
7847         // count the usage for stats
7848         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7849         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7850
7851         return (void *)data;
7852 }
7853
7854 void *R_FrameData_Store(size_t size, void *data)
7855 {
7856         void *d = R_FrameData_Alloc(size);
7857         if (d && data)
7858                 memcpy(d, data, size);
7859         return d;
7860 }
7861
7862 void R_FrameData_SetMark(void)
7863 {
7864         if (!r_framedata_mem)
7865                 return;
7866         r_framedata_mem->mark = r_framedata_mem->current;
7867 }
7868
7869 void R_FrameData_ReturnToMark(void)
7870 {
7871         if (!r_framedata_mem)
7872                 return;
7873         r_framedata_mem->current = r_framedata_mem->mark;
7874 }
7875
7876 //==================================================================================
7877
7878 // LordHavoc: animcache originally written by Echon, rewritten since then
7879
7880 /**
7881  * Animation cache prevents re-generating mesh data for an animated model
7882  * multiple times in one frame for lighting, shadowing, reflections, etc.
7883  */
7884
7885 void R_AnimCache_Free(void)
7886 {
7887 }
7888
7889 void R_AnimCache_ClearCache(void)
7890 {
7891         int i;
7892         entity_render_t *ent;
7893
7894         for (i = 0;i < r_refdef.scene.numentities;i++)
7895         {
7896                 ent = r_refdef.scene.entities[i];
7897                 ent->animcache_vertex3f = NULL;
7898                 ent->animcache_normal3f = NULL;
7899                 ent->animcache_svector3f = NULL;
7900                 ent->animcache_tvector3f = NULL;
7901                 ent->animcache_vertexmesh = NULL;
7902                 ent->animcache_vertex3fbuffer = NULL;
7903                 ent->animcache_vertexmeshbuffer = NULL;
7904         }
7905 }
7906
7907 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7908 {
7909         int i;
7910
7911         // check if we need the meshbuffers
7912         if (!vid.useinterleavedarrays)
7913                 return;
7914
7915         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7916                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7917         // TODO: upload vertex3f buffer?
7918         if (ent->animcache_vertexmesh)
7919         {
7920                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7921                 for (i = 0;i < numvertices;i++)
7922                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7923                 if (ent->animcache_svector3f)
7924                         for (i = 0;i < numvertices;i++)
7925                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7926                 if (ent->animcache_tvector3f)
7927                         for (i = 0;i < numvertices;i++)
7928                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7929                 if (ent->animcache_normal3f)
7930                         for (i = 0;i < numvertices;i++)
7931                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7932                 // TODO: upload vertexmeshbuffer?
7933         }
7934 }
7935
7936 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7937 {
7938         dp_model_t *model = ent->model;
7939         int numvertices;
7940         // see if it's already cached this frame
7941         if (ent->animcache_vertex3f)
7942         {
7943                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7944                 if (wantnormals || wanttangents)
7945                 {
7946                         if (ent->animcache_normal3f)
7947                                 wantnormals = false;
7948                         if (ent->animcache_svector3f)
7949                                 wanttangents = false;
7950                         if (wantnormals || wanttangents)
7951                         {
7952                                 numvertices = model->surfmesh.num_vertices;
7953                                 if (wantnormals)
7954                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7955                                 if (wanttangents)
7956                                 {
7957                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7958                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7959                                 }
7960                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7961                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7962                         }
7963                 }
7964         }
7965         else
7966         {
7967                 // see if this ent is worth caching
7968                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7969                         return false;
7970                 // get some memory for this entity and generate mesh data
7971                 numvertices = model->surfmesh.num_vertices;
7972                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7973                 if (wantnormals)
7974                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7975                 if (wanttangents)
7976                 {
7977                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7978                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7979                 }
7980                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7981                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7982         }
7983         return true;
7984 }
7985
7986 void R_AnimCache_CacheVisibleEntities(void)
7987 {
7988         int i;
7989         qboolean wantnormals = true;
7990         qboolean wanttangents = !r_showsurfaces.integer;
7991
7992         switch(vid.renderpath)
7993         {
7994         case RENDERPATH_GL20:
7995         case RENDERPATH_CGGL:
7996         case RENDERPATH_D3D9:
7997         case RENDERPATH_D3D10:
7998         case RENDERPATH_D3D11:
7999                 break;
8000         case RENDERPATH_GL13:
8001         case RENDERPATH_GL11:
8002                 wanttangents = false;
8003                 break;
8004         case RENDERPATH_SOFT:
8005                 break;
8006         }
8007
8008         if (r_shownormals.integer)
8009                 wanttangents = wantnormals = true;
8010
8011         // TODO: thread this
8012         // NOTE: R_PrepareRTLights() also caches entities
8013
8014         for (i = 0;i < r_refdef.scene.numentities;i++)
8015                 if (r_refdef.viewcache.entityvisible[i])
8016                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
8017 }
8018
8019 //==================================================================================
8020
8021 static void R_View_UpdateEntityLighting (void)
8022 {
8023         int i;
8024         entity_render_t *ent;
8025         vec3_t tempdiffusenormal, avg;
8026         vec_t f, fa, fd, fdd;
8027         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
8028
8029         for (i = 0;i < r_refdef.scene.numentities;i++)
8030         {
8031                 ent = r_refdef.scene.entities[i];
8032
8033                 // skip unseen models
8034                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
8035                         continue;
8036
8037                 // skip bsp models
8038                 if (ent->model && ent->model->brush.num_leafs)
8039                 {
8040                         // TODO: use modellight for r_ambient settings on world?
8041                         VectorSet(ent->modellight_ambient, 0, 0, 0);
8042                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
8043                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
8044                         continue;
8045                 }
8046
8047                 // fetch the lighting from the worldmodel data
8048                 VectorClear(ent->modellight_ambient);
8049                 VectorClear(ent->modellight_diffuse);
8050                 VectorClear(tempdiffusenormal);
8051                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
8052                 {
8053                         vec3_t org;
8054                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8055
8056                         // complete lightning for lit sprites
8057                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
8058                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
8059                         {
8060                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
8061                                         org[2] = org[2] + r_overheadsprites_pushback.value;
8062                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
8063                         }
8064                         else
8065                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
8066
8067                         if(ent->flags & RENDER_EQUALIZE)
8068                         {
8069                                 // first fix up ambient lighting...
8070                                 if(r_equalize_entities_minambient.value > 0)
8071                                 {
8072                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8073                                         if(fd > 0)
8074                                         {
8075                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
8076                                                 if(fa < r_equalize_entities_minambient.value * fd)
8077                                                 {
8078                                                         // solve:
8079                                                         //   fa'/fd' = minambient
8080                                                         //   fa'+0.25*fd' = fa+0.25*fd
8081                                                         //   ...
8082                                                         //   fa' = fd' * minambient
8083                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
8084                                                         //   ...
8085                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
8086                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
8087                                                         //   ...
8088                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
8089                                                         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
8090                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
8091                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
8092                                                 }
8093                                         }
8094                                 }
8095
8096                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
8097                                 {
8098                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
8099                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8100                                         f = fa + 0.25 * fd;
8101                                         if(f > 0)
8102                                         {
8103                                                 // adjust brightness and saturation to target
8104                                                 avg[0] = avg[1] = avg[2] = fa / f;
8105                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
8106                                                 avg[0] = avg[1] = avg[2] = fd / f;
8107                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
8108                                         }
8109                                 }
8110                         }
8111                 }
8112                 else // highly rare
8113                         VectorSet(ent->modellight_ambient, 1, 1, 1);
8114
8115                 // move the light direction into modelspace coordinates for lighting code
8116                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8117                 if(VectorLength2(ent->modellight_lightdir) == 0)
8118                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8119                 VectorNormalize(ent->modellight_lightdir);
8120         }
8121 }
8122
8123 #define MAX_LINEOFSIGHTTRACES 64
8124
8125 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8126 {
8127         int i;
8128         vec3_t boxmins, boxmaxs;
8129         vec3_t start;
8130         vec3_t end;
8131         dp_model_t *model = r_refdef.scene.worldmodel;
8132
8133         if (!model || !model->brush.TraceLineOfSight)
8134                 return true;
8135
8136         // expand the box a little
8137         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8138         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8139         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8140         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8141         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8142         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8143
8144         // return true if eye is inside enlarged box
8145         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8146                 return true;
8147
8148         // try center
8149         VectorCopy(eye, start);
8150         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8151         if (model->brush.TraceLineOfSight(model, start, end))
8152                 return true;
8153
8154         // try various random positions
8155         for (i = 0;i < numsamples;i++)
8156         {
8157                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8158                 if (model->brush.TraceLineOfSight(model, start, end))
8159                         return true;
8160         }
8161
8162         return false;
8163 }
8164
8165
8166 static void R_View_UpdateEntityVisible (void)
8167 {
8168         int i;
8169         int renderimask;
8170         int samples;
8171         entity_render_t *ent;
8172
8173         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8174                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8175                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8176                 :                                                          RENDER_EXTERIORMODEL;
8177         if (!r_drawviewmodel.integer)
8178                 renderimask |= RENDER_VIEWMODEL;
8179         if (!r_drawexteriormodel.integer)
8180                 renderimask |= RENDER_EXTERIORMODEL;
8181         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8182         {
8183                 // worldmodel can check visibility
8184                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8185                 for (i = 0;i < r_refdef.scene.numentities;i++)
8186                 {
8187                         ent = r_refdef.scene.entities[i];
8188                         if (!(ent->flags & renderimask))
8189                         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)))
8190                         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))
8191                                 r_refdef.viewcache.entityvisible[i] = true;
8192                 }
8193                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8194                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8195                 {
8196                         for (i = 0;i < r_refdef.scene.numentities;i++)
8197                         {
8198                                 ent = r_refdef.scene.entities[i];
8199                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8200                                 {
8201                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8202                                         if (samples < 0)
8203                                                 continue; // temp entities do pvs only
8204                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8205                                                 ent->last_trace_visibility = realtime;
8206                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8207                                                 r_refdef.viewcache.entityvisible[i] = 0;
8208                                 }
8209                         }
8210                 }
8211         }
8212         else
8213         {
8214                 // no worldmodel or it can't check visibility
8215                 for (i = 0;i < r_refdef.scene.numentities;i++)
8216                 {
8217                         ent = r_refdef.scene.entities[i];
8218                         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));
8219                 }
8220         }
8221 }
8222
8223 /// only used if skyrendermasked, and normally returns false
8224 int R_DrawBrushModelsSky (void)
8225 {
8226         int i, sky;
8227         entity_render_t *ent;
8228
8229         sky = false;
8230         for (i = 0;i < r_refdef.scene.numentities;i++)
8231         {
8232                 if (!r_refdef.viewcache.entityvisible[i])
8233                         continue;
8234                 ent = r_refdef.scene.entities[i];
8235                 if (!ent->model || !ent->model->DrawSky)
8236                         continue;
8237                 ent->model->DrawSky(ent);
8238                 sky = true;
8239         }
8240         return sky;
8241 }
8242
8243 static void R_DrawNoModel(entity_render_t *ent);
8244 static void R_DrawModels(void)
8245 {
8246         int i;
8247         entity_render_t *ent;
8248
8249         for (i = 0;i < r_refdef.scene.numentities;i++)
8250         {
8251                 if (!r_refdef.viewcache.entityvisible[i])
8252                         continue;
8253                 ent = r_refdef.scene.entities[i];
8254                 r_refdef.stats.entities++;
8255                 if (ent->model && ent->model->Draw != NULL)
8256                         ent->model->Draw(ent);
8257                 else
8258                         R_DrawNoModel(ent);
8259         }
8260 }
8261
8262 static void R_DrawModelsDepth(void)
8263 {
8264         int i;
8265         entity_render_t *ent;
8266
8267         for (i = 0;i < r_refdef.scene.numentities;i++)
8268         {
8269                 if (!r_refdef.viewcache.entityvisible[i])
8270                         continue;
8271                 ent = r_refdef.scene.entities[i];
8272                 if (ent->model && ent->model->DrawDepth != NULL)
8273                         ent->model->DrawDepth(ent);
8274         }
8275 }
8276
8277 static void R_DrawModelsDebug(void)
8278 {
8279         int i;
8280         entity_render_t *ent;
8281
8282         for (i = 0;i < r_refdef.scene.numentities;i++)
8283         {
8284                 if (!r_refdef.viewcache.entityvisible[i])
8285                         continue;
8286                 ent = r_refdef.scene.entities[i];
8287                 if (ent->model && ent->model->DrawDebug != NULL)
8288                         ent->model->DrawDebug(ent);
8289         }
8290 }
8291
8292 static void R_DrawModelsAddWaterPlanes(void)
8293 {
8294         int i;
8295         entity_render_t *ent;
8296
8297         for (i = 0;i < r_refdef.scene.numentities;i++)
8298         {
8299                 if (!r_refdef.viewcache.entityvisible[i])
8300                         continue;
8301                 ent = r_refdef.scene.entities[i];
8302                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8303                         ent->model->DrawAddWaterPlanes(ent);
8304         }
8305 }
8306
8307 static void R_View_SetFrustum(const int *scissor)
8308 {
8309         int i;
8310         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8311         vec3_t forward, left, up, origin, v;
8312
8313         if(scissor)
8314         {
8315                 // flipped x coordinates (because x points left here)
8316                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8317                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8318
8319                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8320                 switch(vid.renderpath)
8321                 {
8322                         case RENDERPATH_D3D9:
8323                         case RENDERPATH_D3D10:
8324                         case RENDERPATH_D3D11:
8325                         case RENDERPATH_SOFT:
8326                                 // non-flipped y coordinates
8327                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8328                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8329                                 break;
8330                         case RENDERPATH_GL11:
8331                         case RENDERPATH_GL13:
8332                         case RENDERPATH_GL20:
8333                         case RENDERPATH_CGGL:
8334                                 // non-flipped y coordinates
8335                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8336                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8337                                 break;
8338                 }
8339         }
8340
8341         // we can't trust r_refdef.view.forward and friends in reflected scenes
8342         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8343
8344 #if 0
8345         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8346         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8347         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8348         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8349         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8350         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8351         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8352         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8353         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8354         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8355         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8356         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8357 #endif
8358
8359 #if 0
8360         zNear = r_refdef.nearclip;
8361         nudge = 1.0 - 1.0 / (1<<23);
8362         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8363         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8364         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8365         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8366         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8367         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8368         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8369         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8370 #endif
8371
8372
8373
8374 #if 0
8375         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8376         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8377         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8378         r_refdef.view.frustum[0].dist = m[15] - m[12];
8379
8380         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8381         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8382         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8383         r_refdef.view.frustum[1].dist = m[15] + m[12];
8384
8385         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8386         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8387         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8388         r_refdef.view.frustum[2].dist = m[15] - m[13];
8389
8390         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8391         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8392         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8393         r_refdef.view.frustum[3].dist = m[15] + m[13];
8394
8395         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8396         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8397         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8398         r_refdef.view.frustum[4].dist = m[15] - m[14];
8399
8400         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8401         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8402         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8403         r_refdef.view.frustum[5].dist = m[15] + m[14];
8404 #endif
8405
8406         if (r_refdef.view.useperspective)
8407         {
8408                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8409                 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]);
8410                 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]);
8411                 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]);
8412                 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]);
8413
8414                 // then the normals from the corners relative to origin
8415                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8416                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8417                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8418                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8419
8420                 // in a NORMAL view, forward cross left == up
8421                 // in a REFLECTED view, forward cross left == down
8422                 // so our cross products above need to be adjusted for a left handed coordinate system
8423                 CrossProduct(forward, left, v);
8424                 if(DotProduct(v, up) < 0)
8425                 {
8426                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8427                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8428                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8429                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8430                 }
8431
8432                 // Leaving those out was a mistake, those were in the old code, and they
8433                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8434                 // I couldn't reproduce it after adding those normalizations. --blub
8435                 VectorNormalize(r_refdef.view.frustum[0].normal);
8436                 VectorNormalize(r_refdef.view.frustum[1].normal);
8437                 VectorNormalize(r_refdef.view.frustum[2].normal);
8438                 VectorNormalize(r_refdef.view.frustum[3].normal);
8439
8440                 // make the corners absolute
8441                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8442                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8443                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8444                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8445
8446                 // one more normal
8447                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8448
8449                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8450                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8451                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8452                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8453                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8454         }
8455         else
8456         {
8457                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8458                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8459                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8460                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8461                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8462                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8463                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8464                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8465                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8466                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8467         }
8468         r_refdef.view.numfrustumplanes = 5;
8469
8470         if (r_refdef.view.useclipplane)
8471         {
8472                 r_refdef.view.numfrustumplanes = 6;
8473                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8474         }
8475
8476         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8477                 PlaneClassify(r_refdef.view.frustum + i);
8478
8479         // LordHavoc: note to all quake engine coders, Quake had a special case
8480         // for 90 degrees which assumed a square view (wrong), so I removed it,
8481         // Quake2 has it disabled as well.
8482
8483         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8484         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8485         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8486         //PlaneClassify(&frustum[0]);
8487
8488         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8489         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8490         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8491         //PlaneClassify(&frustum[1]);
8492
8493         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8494         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8495         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8496         //PlaneClassify(&frustum[2]);
8497
8498         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8499         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8500         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8501         //PlaneClassify(&frustum[3]);
8502
8503         // nearclip plane
8504         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8505         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8506         //PlaneClassify(&frustum[4]);
8507 }
8508
8509 void R_View_UpdateWithScissor(const int *myscissor)
8510 {
8511         R_Main_ResizeViewCache();
8512         R_View_SetFrustum(myscissor);
8513         R_View_WorldVisibility(r_refdef.view.useclipplane);
8514         R_View_UpdateEntityVisible();
8515         R_View_UpdateEntityLighting();
8516 }
8517
8518 void R_View_Update(void)
8519 {
8520         R_Main_ResizeViewCache();
8521         R_View_SetFrustum(NULL);
8522         R_View_WorldVisibility(r_refdef.view.useclipplane);
8523         R_View_UpdateEntityVisible();
8524         R_View_UpdateEntityLighting();
8525 }
8526
8527 void R_SetupView(qboolean allowwaterclippingplane)
8528 {
8529         const float *customclipplane = NULL;
8530         float plane[4];
8531         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8532         {
8533                 // LordHavoc: couldn't figure out how to make this approach the
8534                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8535                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8536                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8537                         dist = r_refdef.view.clipplane.dist;
8538                 plane[0] = r_refdef.view.clipplane.normal[0];
8539                 plane[1] = r_refdef.view.clipplane.normal[1];
8540                 plane[2] = r_refdef.view.clipplane.normal[2];
8541                 plane[3] = dist;
8542                 customclipplane = plane;
8543         }
8544
8545         if (!r_refdef.view.useperspective)
8546                 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);
8547         else if (vid.stencil && r_useinfinitefarclip.integer)
8548                 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);
8549         else
8550                 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);
8551         R_SetViewport(&r_refdef.view.viewport);
8552 }
8553
8554 void R_EntityMatrix(const matrix4x4_t *matrix)
8555 {
8556         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8557         {
8558                 gl_modelmatrixchanged = false;
8559                 gl_modelmatrix = *matrix;
8560                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8561                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8562                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8563                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8564                 CHECKGLERROR
8565                 switch(vid.renderpath)
8566                 {
8567                 case RENDERPATH_D3D9:
8568 #ifdef SUPPORTD3D
8569                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8570                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8571 #endif
8572                         break;
8573                 case RENDERPATH_D3D10:
8574                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8575                         break;
8576                 case RENDERPATH_D3D11:
8577                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8578                         break;
8579                 case RENDERPATH_GL20:
8580                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8581                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8582                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8583                         break;
8584                 case RENDERPATH_CGGL:
8585 #ifdef SUPPORTCG
8586                         CHECKCGERROR
8587                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8588                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8589                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8590 #endif
8591                         break;
8592                 case RENDERPATH_GL13:
8593                 case RENDERPATH_GL11:
8594                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8595                         break;
8596                 case RENDERPATH_SOFT:
8597                         DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
8598                         DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
8599                         break;
8600                 }
8601         }
8602 }
8603
8604 void R_ResetViewRendering2D(void)
8605 {
8606         r_viewport_t viewport;
8607         DrawQ_Finish();
8608
8609         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8610         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);
8611         R_SetViewport(&viewport);
8612         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8613         GL_Color(1, 1, 1, 1);
8614         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8615         GL_BlendFunc(GL_ONE, GL_ZERO);
8616         GL_AlphaTest(false);
8617         GL_ScissorTest(false);
8618         GL_DepthMask(false);
8619         GL_DepthRange(0, 1);
8620         GL_DepthTest(false);
8621         GL_DepthFunc(GL_LEQUAL);
8622         R_EntityMatrix(&identitymatrix);
8623         R_Mesh_ResetTextureState();
8624         GL_PolygonOffset(0, 0);
8625         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8626         switch(vid.renderpath)
8627         {
8628         case RENDERPATH_GL11:
8629         case RENDERPATH_GL13:
8630         case RENDERPATH_GL20:
8631         case RENDERPATH_CGGL:
8632                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8633                 break;
8634         case RENDERPATH_D3D9:
8635         case RENDERPATH_D3D10:
8636         case RENDERPATH_D3D11:
8637         case RENDERPATH_SOFT:
8638                 break;
8639         }
8640         GL_CullFace(GL_NONE);
8641 }
8642
8643 void R_ResetViewRendering3D(void)
8644 {
8645         DrawQ_Finish();
8646
8647         R_SetupView(true);
8648         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8649         GL_Color(1, 1, 1, 1);
8650         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8651         GL_BlendFunc(GL_ONE, GL_ZERO);
8652         GL_AlphaTest(false);
8653         GL_ScissorTest(true);
8654         GL_DepthMask(true);
8655         GL_DepthRange(0, 1);
8656         GL_DepthTest(true);
8657         GL_DepthFunc(GL_LEQUAL);
8658         R_EntityMatrix(&identitymatrix);
8659         R_Mesh_ResetTextureState();
8660         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8661         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8662         switch(vid.renderpath)
8663         {
8664         case RENDERPATH_GL11:
8665         case RENDERPATH_GL13:
8666         case RENDERPATH_GL20:
8667         case RENDERPATH_CGGL:
8668                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8669                 break;
8670         case RENDERPATH_D3D9:
8671         case RENDERPATH_D3D10:
8672         case RENDERPATH_D3D11:
8673         case RENDERPATH_SOFT:
8674                 break;
8675         }
8676         GL_CullFace(r_refdef.view.cullface_back);
8677 }
8678
8679 /*
8680 ================
8681 R_RenderView_UpdateViewVectors
8682 ================
8683 */
8684 static void R_RenderView_UpdateViewVectors(void)
8685 {
8686         // break apart the view matrix into vectors for various purposes
8687         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8688         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8689         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8690         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8691         // make an inverted copy of the view matrix for tracking sprites
8692         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8693 }
8694
8695 void R_RenderScene(void);
8696 void R_RenderWaterPlanes(void);
8697
8698 static void R_Water_StartFrame(void)
8699 {
8700         int i;
8701         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8702         r_waterstate_waterplane_t *p;
8703
8704         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8705                 return;
8706
8707         switch(vid.renderpath)
8708         {
8709         case RENDERPATH_GL20:
8710         case RENDERPATH_CGGL:
8711         case RENDERPATH_D3D9:
8712         case RENDERPATH_D3D10:
8713         case RENDERPATH_D3D11:
8714         case RENDERPATH_SOFT:
8715                 break;
8716         case RENDERPATH_GL13:
8717         case RENDERPATH_GL11:
8718                 return;
8719         }
8720
8721         // set waterwidth and waterheight to the water resolution that will be
8722         // used (often less than the screen resolution for faster rendering)
8723         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8724         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8725
8726         // calculate desired texture sizes
8727         // can't use water if the card does not support the texture size
8728         if (!r_water.integer || r_showsurfaces.integer)
8729                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8730         else if (vid.support.arb_texture_non_power_of_two)
8731         {
8732                 texturewidth = waterwidth;
8733                 textureheight = waterheight;
8734                 camerawidth = waterwidth;
8735                 cameraheight = waterheight;
8736         }
8737         else
8738         {
8739                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8740                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8741                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8742                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8743         }
8744
8745         // allocate textures as needed
8746         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8747         {
8748                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8749                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8750                 {
8751                         if (p->texture_refraction)
8752                                 R_FreeTexture(p->texture_refraction);
8753                         p->texture_refraction = NULL;
8754                         if (p->texture_reflection)
8755                                 R_FreeTexture(p->texture_reflection);
8756                         p->texture_reflection = NULL;
8757                         if (p->texture_camera)
8758                                 R_FreeTexture(p->texture_camera);
8759                         p->texture_camera = NULL;
8760                 }
8761                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8762                 r_waterstate.texturewidth = texturewidth;
8763                 r_waterstate.textureheight = textureheight;
8764                 r_waterstate.camerawidth = camerawidth;
8765                 r_waterstate.cameraheight = cameraheight;
8766         }
8767
8768         if (r_waterstate.texturewidth)
8769         {
8770                 r_waterstate.enabled = true;
8771
8772                 // when doing a reduced render (HDR) we want to use a smaller area
8773                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8774                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8775
8776                 // set up variables that will be used in shader setup
8777                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8778                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8779                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8780                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8781         }
8782
8783         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8784         r_waterstate.numwaterplanes = 0;
8785 }
8786
8787 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8788 {
8789         int triangleindex, planeindex;
8790         const int *e;
8791         vec3_t vert[3];
8792         vec3_t normal;
8793         vec3_t center;
8794         mplane_t plane;
8795         r_waterstate_waterplane_t *p;
8796         texture_t *t = R_GetCurrentTexture(surface->texture);
8797
8798         // just use the first triangle with a valid normal for any decisions
8799         VectorClear(normal);
8800         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8801         {
8802                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8803                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8804                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8805                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8806                 if (VectorLength2(normal) >= 0.001)
8807                         break;
8808         }
8809
8810         VectorCopy(normal, plane.normal);
8811         VectorNormalize(plane.normal);
8812         plane.dist = DotProduct(vert[0], plane.normal);
8813         PlaneClassify(&plane);
8814         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8815         {
8816                 // skip backfaces (except if nocullface is set)
8817                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8818                         return;
8819                 VectorNegate(plane.normal, plane.normal);
8820                 plane.dist *= -1;
8821                 PlaneClassify(&plane);
8822         }
8823
8824
8825         // find a matching plane if there is one
8826         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8827                 if(p->camera_entity == t->camera_entity)
8828                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8829                                 break;
8830         if (planeindex >= r_waterstate.maxwaterplanes)
8831                 return; // nothing we can do, out of planes
8832
8833         // if this triangle does not fit any known plane rendered this frame, add one
8834         if (planeindex >= r_waterstate.numwaterplanes)
8835         {
8836                 // store the new plane
8837                 r_waterstate.numwaterplanes++;
8838                 p->plane = plane;
8839                 // clear materialflags and pvs
8840                 p->materialflags = 0;
8841                 p->pvsvalid = false;
8842                 p->camera_entity = t->camera_entity;
8843                 VectorCopy(surface->mins, p->mins);
8844                 VectorCopy(surface->maxs, p->maxs);
8845         }
8846         else
8847         {
8848                 // merge mins/maxs
8849                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8850                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8851                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8852                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8853                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8854                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8855         }
8856         // merge this surface's materialflags into the waterplane
8857         p->materialflags |= t->currentmaterialflags;
8858         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8859         {
8860                 // merge this surface's PVS into the waterplane
8861                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8862                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8863                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8864                 {
8865                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8866                         p->pvsvalid = true;
8867                 }
8868         }
8869 }
8870
8871 static void R_Water_ProcessPlanes(void)
8872 {
8873         int myscissor[4];
8874         r_refdef_view_t originalview;
8875         r_refdef_view_t myview;
8876         int planeindex;
8877         r_waterstate_waterplane_t *p;
8878         vec3_t visorigin;
8879
8880         originalview = r_refdef.view;
8881
8882         // make sure enough textures are allocated
8883         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8884         {
8885                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8886                 {
8887                         if (!p->texture_refraction)
8888                                 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);
8889                         if (!p->texture_refraction)
8890                                 goto error;
8891                 }
8892                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8893                 {
8894                         if (!p->texture_camera)
8895                                 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);
8896                         if (!p->texture_camera)
8897                                 goto error;
8898                 }
8899
8900                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8901                 {
8902                         if (!p->texture_reflection)
8903                                 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);
8904                         if (!p->texture_reflection)
8905                                 goto error;
8906                 }
8907         }
8908
8909         // render views
8910         r_refdef.view = originalview;
8911         r_refdef.view.showdebug = false;
8912         r_refdef.view.width = r_waterstate.waterwidth;
8913         r_refdef.view.height = r_waterstate.waterheight;
8914         r_refdef.view.useclipplane = true;
8915         myview = r_refdef.view;
8916         r_waterstate.renderingscene = true;
8917         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8918         {
8919                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8920                 {
8921                         r_refdef.view = myview;
8922                         if(r_water_scissormode.integer)
8923                         {
8924                                 R_SetupView(true);
8925                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8926                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8927                         }
8928
8929                         // render reflected scene and copy into texture
8930                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8931                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8932                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8933                         r_refdef.view.clipplane = p->plane;
8934
8935                         // reverse the cullface settings for this render
8936                         r_refdef.view.cullface_front = GL_FRONT;
8937                         r_refdef.view.cullface_back = GL_BACK;
8938                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8939                         {
8940                                 r_refdef.view.usecustompvs = true;
8941                                 if (p->pvsvalid)
8942                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8943                                 else
8944                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8945                         }
8946
8947                         R_ResetViewRendering3D();
8948                         R_ClearScreen(r_refdef.fogenabled);
8949                         if(r_water_scissormode.integer & 2)
8950                                 R_View_UpdateWithScissor(myscissor);
8951                         else
8952                                 R_View_Update();
8953                         if(r_water_scissormode.integer & 1)
8954                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8955                         R_RenderScene();
8956
8957                         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);
8958                 }
8959
8960                 // render the normal view scene and copy into texture
8961                 // (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)
8962                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8963                 {
8964                         r_refdef.view = myview;
8965                         if(r_water_scissormode.integer)
8966                         {
8967                                 R_SetupView(true);
8968                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8969                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8970                         }
8971
8972                         r_waterstate.renderingrefraction = true;
8973
8974                         r_refdef.view.clipplane = p->plane;
8975                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8976                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8977
8978                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8979                         {
8980                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8981                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8982                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8983                                 R_RenderView_UpdateViewVectors();
8984                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8985                                 {
8986                                         r_refdef.view.usecustompvs = true;
8987                                         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);
8988                                 }
8989                         }
8990
8991                         PlaneClassify(&r_refdef.view.clipplane);
8992
8993                         R_ResetViewRendering3D();
8994                         R_ClearScreen(r_refdef.fogenabled);
8995                         if(r_water_scissormode.integer & 2)
8996                                 R_View_UpdateWithScissor(myscissor);
8997                         else
8998                                 R_View_Update();
8999                         if(r_water_scissormode.integer & 1)
9000                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
9001                         R_RenderScene();
9002
9003                         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);
9004                         r_waterstate.renderingrefraction = false;
9005                 }
9006                 else if (p->materialflags & MATERIALFLAG_CAMERA)
9007                 {
9008                         r_refdef.view = myview;
9009
9010                         r_refdef.view.clipplane = p->plane;
9011                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
9012                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
9013
9014                         r_refdef.view.width = r_waterstate.camerawidth;
9015                         r_refdef.view.height = r_waterstate.cameraheight;
9016                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
9017                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
9018
9019                         if(p->camera_entity)
9020                         {
9021                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
9022                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
9023                         }
9024
9025                         // note: all of the view is used for displaying... so
9026                         // there is no use in scissoring
9027
9028                         // reverse the cullface settings for this render
9029                         r_refdef.view.cullface_front = GL_FRONT;
9030                         r_refdef.view.cullface_back = GL_BACK;
9031                         // also reverse the view matrix
9032                         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
9033                         R_RenderView_UpdateViewVectors();
9034                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
9035                         {
9036                                 r_refdef.view.usecustompvs = true;
9037                                 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);
9038                         }
9039                         
9040                         // camera needs no clipplane
9041                         r_refdef.view.useclipplane = false;
9042
9043                         PlaneClassify(&r_refdef.view.clipplane);
9044
9045                         R_ResetViewRendering3D();
9046                         R_ClearScreen(r_refdef.fogenabled);
9047                         R_View_Update();
9048                         R_RenderScene();
9049
9050                         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);
9051                         r_waterstate.renderingrefraction = false;
9052                 }
9053
9054         }
9055         r_waterstate.renderingscene = false;
9056         r_refdef.view = originalview;
9057         R_ResetViewRendering3D();
9058         R_ClearScreen(r_refdef.fogenabled);
9059         R_View_Update();
9060         return;
9061 error:
9062         r_refdef.view = originalview;
9063         r_waterstate.renderingscene = false;
9064         Cvar_SetValueQuick(&r_water, 0);
9065         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
9066         return;
9067 }
9068
9069 void R_Bloom_StartFrame(void)
9070 {
9071         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
9072
9073         switch(vid.renderpath)
9074         {
9075         case RENDERPATH_GL20:
9076         case RENDERPATH_CGGL:
9077         case RENDERPATH_D3D9:
9078         case RENDERPATH_D3D10:
9079         case RENDERPATH_D3D11:
9080         case RENDERPATH_SOFT:
9081                 break;
9082         case RENDERPATH_GL13:
9083         case RENDERPATH_GL11:
9084                 return;
9085         }
9086
9087         // set bloomwidth and bloomheight to the bloom resolution that will be
9088         // used (often less than the screen resolution for faster rendering)
9089         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
9090         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
9091         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
9092         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
9093         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
9094
9095         // calculate desired texture sizes
9096         if (vid.support.arb_texture_non_power_of_two)
9097         {
9098                 screentexturewidth = r_refdef.view.width;
9099                 screentextureheight = r_refdef.view.height;
9100                 bloomtexturewidth = r_bloomstate.bloomwidth;
9101                 bloomtextureheight = r_bloomstate.bloomheight;
9102         }
9103         else
9104         {
9105                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
9106                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
9107                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
9108                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
9109         }
9110
9111         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))
9112         {
9113                 Cvar_SetValueQuick(&r_hdr, 0);
9114                 Cvar_SetValueQuick(&r_bloom, 0);
9115                 Cvar_SetValueQuick(&r_motionblur, 0);
9116                 Cvar_SetValueQuick(&r_damageblur, 0);
9117         }
9118
9119         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)))
9120                 screentexturewidth = screentextureheight = 0;
9121         if (!r_hdr.integer && !r_bloom.integer)
9122                 bloomtexturewidth = bloomtextureheight = 0;
9123
9124         // allocate textures as needed
9125         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
9126         {
9127                 if (r_bloomstate.texture_screen)
9128                         R_FreeTexture(r_bloomstate.texture_screen);
9129                 r_bloomstate.texture_screen = NULL;
9130                 r_bloomstate.screentexturewidth = screentexturewidth;
9131                 r_bloomstate.screentextureheight = screentextureheight;
9132                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
9133                         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);
9134         }
9135         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
9136         {
9137                 if (r_bloomstate.texture_bloom)
9138                         R_FreeTexture(r_bloomstate.texture_bloom);
9139                 r_bloomstate.texture_bloom = NULL;
9140                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9141                 r_bloomstate.bloomtextureheight = bloomtextureheight;
9142                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9143                         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);
9144         }
9145
9146         // when doing a reduced render (HDR) we want to use a smaller area
9147         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9148         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9149         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9150         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9151         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9152
9153         // set up a texcoord array for the full resolution screen image
9154         // (we have to keep this around to copy back during final render)
9155         r_bloomstate.screentexcoord2f[0] = 0;
9156         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9157         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9158         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9159         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9160         r_bloomstate.screentexcoord2f[5] = 0;
9161         r_bloomstate.screentexcoord2f[6] = 0;
9162         r_bloomstate.screentexcoord2f[7] = 0;
9163
9164         // set up a texcoord array for the reduced resolution bloom image
9165         // (which will be additive blended over the screen image)
9166         r_bloomstate.bloomtexcoord2f[0] = 0;
9167         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9168         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9169         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9170         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9171         r_bloomstate.bloomtexcoord2f[5] = 0;
9172         r_bloomstate.bloomtexcoord2f[6] = 0;
9173         r_bloomstate.bloomtexcoord2f[7] = 0;
9174
9175         switch(vid.renderpath)
9176         {
9177         case RENDERPATH_GL11:
9178         case RENDERPATH_GL13:
9179         case RENDERPATH_GL20:
9180         case RENDERPATH_CGGL:
9181         case RENDERPATH_SOFT:
9182                 break;
9183         case RENDERPATH_D3D9:
9184         case RENDERPATH_D3D10:
9185         case RENDERPATH_D3D11:
9186                 {
9187                         int i;
9188                         for (i = 0;i < 4;i++)
9189                         {
9190                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9191                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9192                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9193                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9194                         }
9195                 }
9196                 break;
9197         }
9198
9199         if (r_hdr.integer || r_bloom.integer)
9200         {
9201                 r_bloomstate.enabled = true;
9202                 r_bloomstate.hdr = r_hdr.integer != 0;
9203         }
9204
9205         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);
9206 }
9207
9208 void R_Bloom_CopyBloomTexture(float colorscale)
9209 {
9210         r_refdef.stats.bloom++;
9211
9212         // scale down screen texture to the bloom texture size
9213         CHECKGLERROR
9214         R_SetViewport(&r_bloomstate.viewport);
9215         GL_BlendFunc(GL_ONE, GL_ZERO);
9216         GL_Color(colorscale, colorscale, colorscale, 1);
9217         // 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...
9218         switch(vid.renderpath)
9219         {
9220         case RENDERPATH_GL11:
9221         case RENDERPATH_GL13:
9222         case RENDERPATH_GL20:
9223         case RENDERPATH_CGGL:
9224         case RENDERPATH_SOFT:
9225                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9226                 break;
9227         case RENDERPATH_D3D9:
9228         case RENDERPATH_D3D10:
9229         case RENDERPATH_D3D11:
9230                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9231                 break;
9232         }
9233         // TODO: do boxfilter scale-down in shader?
9234         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9235         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9236         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9237
9238         // we now have a bloom image in the framebuffer
9239         // copy it into the bloom image texture for later processing
9240         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);
9241         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9242 }
9243
9244 void R_Bloom_CopyHDRTexture(void)
9245 {
9246         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);
9247         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9248 }
9249
9250 void R_Bloom_MakeTexture(void)
9251 {
9252         int x, range, dir;
9253         float xoffset, yoffset, r, brighten;
9254
9255         r_refdef.stats.bloom++;
9256
9257         R_ResetViewRendering2D();
9258
9259         // we have a bloom image in the framebuffer
9260         CHECKGLERROR
9261         R_SetViewport(&r_bloomstate.viewport);
9262
9263         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9264         {
9265                 x *= 2;
9266                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9267                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9268                 GL_Color(r,r,r,1);
9269                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9270                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9271                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9272                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9273
9274                 // copy the vertically blurred bloom view to a texture
9275                 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);
9276                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9277         }
9278
9279         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9280         brighten = r_bloom_brighten.value;
9281         if (r_hdr.integer)
9282                 brighten *= r_hdr_range.value;
9283         brighten = sqrt(brighten);
9284         if(range >= 1)
9285                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9286         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9287
9288         for (dir = 0;dir < 2;dir++)
9289         {
9290                 // blend on at multiple vertical offsets to achieve a vertical blur
9291                 // TODO: do offset blends using GLSL
9292                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9293                 GL_BlendFunc(GL_ONE, GL_ZERO);
9294                 for (x = -range;x <= range;x++)
9295                 {
9296                         if (!dir){xoffset = 0;yoffset = x;}
9297                         else {xoffset = x;yoffset = 0;}
9298                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9299                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9300                         // compute a texcoord array with the specified x and y offset
9301                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9302                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9303                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9304                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9305                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9306                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9307                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9308                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9309                         // this r value looks like a 'dot' particle, fading sharply to
9310                         // black at the edges
9311                         // (probably not realistic but looks good enough)
9312                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9313                         //r = brighten/(range*2+1);
9314                         r = brighten / (range * 2 + 1);
9315                         if(range >= 1)
9316                                 r *= (1 - x*x/(float)(range*range));
9317                         GL_Color(r, r, r, 1);
9318                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9319                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9320                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9321                         GL_BlendFunc(GL_ONE, GL_ONE);
9322                 }
9323
9324                 // copy the vertically blurred bloom view to a texture
9325                 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);
9326                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9327         }
9328 }
9329
9330 void R_HDR_RenderBloomTexture(void)
9331 {
9332         int oldwidth, oldheight;
9333         float oldcolorscale;
9334         qboolean oldwaterstate;
9335
9336         oldwaterstate = r_waterstate.enabled;
9337         oldcolorscale = r_refdef.view.colorscale;
9338         oldwidth = r_refdef.view.width;
9339         oldheight = r_refdef.view.height;
9340         r_refdef.view.width = r_bloomstate.bloomwidth;
9341         r_refdef.view.height = r_bloomstate.bloomheight;
9342
9343         if(r_hdr.integer < 2)
9344                 r_waterstate.enabled = false;
9345
9346         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9347         // TODO: add exposure compensation features
9348         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9349
9350         r_refdef.view.showdebug = false;
9351         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9352
9353         R_ResetViewRendering3D();
9354
9355         R_ClearScreen(r_refdef.fogenabled);
9356         if (r_timereport_active)
9357                 R_TimeReport("HDRclear");
9358
9359         R_View_Update();
9360         if (r_timereport_active)
9361                 R_TimeReport("visibility");
9362
9363         // only do secondary renders with HDR if r_hdr is 2 or higher
9364         r_waterstate.numwaterplanes = 0;
9365         if (r_waterstate.enabled)
9366                 R_RenderWaterPlanes();
9367
9368         r_refdef.view.showdebug = true;
9369         R_RenderScene();
9370         r_waterstate.numwaterplanes = 0;
9371
9372         R_ResetViewRendering2D();
9373
9374         R_Bloom_CopyHDRTexture();
9375         R_Bloom_MakeTexture();
9376
9377         // restore the view settings
9378         r_waterstate.enabled = oldwaterstate;
9379         r_refdef.view.width = oldwidth;
9380         r_refdef.view.height = oldheight;
9381         r_refdef.view.colorscale = oldcolorscale;
9382
9383         R_ResetViewRendering3D();
9384
9385         R_ClearScreen(r_refdef.fogenabled);
9386         if (r_timereport_active)
9387                 R_TimeReport("viewclear");
9388 }
9389
9390 static void R_BlendView(void)
9391 {
9392         unsigned int permutation;
9393         float uservecs[4][4];
9394
9395         switch (vid.renderpath)
9396         {
9397         case RENDERPATH_GL20:
9398         case RENDERPATH_CGGL:
9399         case RENDERPATH_D3D9:
9400         case RENDERPATH_D3D10:
9401         case RENDERPATH_D3D11:
9402         case RENDERPATH_SOFT:
9403                 permutation =
9404                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9405                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9406                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9407                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9408                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9409
9410                 if (r_bloomstate.texture_screen)
9411                 {
9412                         // make sure the buffer is available
9413                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9414
9415                         R_ResetViewRendering2D();
9416
9417                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9418                         {
9419                                 // declare variables
9420                                 float speed;
9421                                 static float avgspeed;
9422
9423                                 speed = VectorLength(cl.movement_velocity);
9424
9425                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9426                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9427
9428                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9429                                 speed = bound(0, speed, 1);
9430                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9431
9432                                 // calculate values into a standard alpha
9433                                 cl.motionbluralpha = 1 - exp(-
9434                                                 (
9435                                                  (r_motionblur.value * speed / 80)
9436                                                  +
9437                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9438                                                 )
9439                                                 /
9440                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9441                                            );
9442
9443                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9444                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9445                                 // apply the blur
9446                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9447                                 {
9448                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9449                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9450                                         switch(vid.renderpath)
9451                                         {
9452                                         case RENDERPATH_GL11:
9453                                         case RENDERPATH_GL13:
9454                                         case RENDERPATH_GL20:
9455                                         case RENDERPATH_CGGL:
9456                                         case RENDERPATH_SOFT:
9457                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9458                                                 break;
9459                                         case RENDERPATH_D3D9:
9460                                         case RENDERPATH_D3D10:
9461                                         case RENDERPATH_D3D11:
9462                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9463                                                 break;
9464                                         }
9465                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9466                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9467                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9468                                 }
9469                         }
9470
9471                         // copy view into the screen texture
9472                         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);
9473                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9474                 }
9475                 else if (!r_bloomstate.texture_bloom)
9476                 {
9477                         // we may still have to do view tint...
9478                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9479                         {
9480                                 // apply a color tint to the whole view
9481                                 R_ResetViewRendering2D();
9482                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9483                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9484                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9485                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9486                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9487                         }
9488                         break; // no screen processing, no bloom, skip it
9489                 }
9490
9491                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9492                 {
9493                         // render simple bloom effect
9494                         // copy the screen and shrink it and darken it for the bloom process
9495                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9496                         // make the bloom texture
9497                         R_Bloom_MakeTexture();
9498                 }
9499
9500 #if _MSC_VER >= 1400
9501 #define sscanf sscanf_s
9502 #endif
9503                 memset(uservecs, 0, sizeof(uservecs));
9504                 if (r_glsl_postprocess_uservec1_enable.integer)
9505                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9506                 if (r_glsl_postprocess_uservec2_enable.integer)
9507                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9508                 if (r_glsl_postprocess_uservec3_enable.integer)
9509                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9510                 if (r_glsl_postprocess_uservec4_enable.integer)
9511                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9512
9513                 R_ResetViewRendering2D();
9514                 GL_Color(1, 1, 1, 1);
9515                 GL_BlendFunc(GL_ONE, GL_ZERO);
9516
9517                 switch(vid.renderpath)
9518                 {
9519                 case RENDERPATH_GL20:
9520                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9521                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9522                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9523                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9524                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9525                         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]);
9526                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9527                         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]);
9528                         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]);
9529                         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]);
9530                         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]);
9531                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9532                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9533                         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);
9534                         break;
9535                 case RENDERPATH_CGGL:
9536 #ifdef SUPPORTCG
9537                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9538                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9539                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9540                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9541                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9542                         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
9543                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9544                         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
9545                         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
9546                         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
9547                         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
9548                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9549                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9550                         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);
9551 #endif
9552                         break;
9553                 case RENDERPATH_D3D9:
9554 #ifdef SUPPORTD3D
9555                         // 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...
9556                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9557                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9558                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9559                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9560                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9561                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9562                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9563                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9564                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9565                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9566                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9567                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9568                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9569                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9570 #endif
9571                         break;
9572                 case RENDERPATH_D3D10:
9573                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9574                         break;
9575                 case RENDERPATH_D3D11:
9576                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9577                         break;
9578                 case RENDERPATH_SOFT:
9579                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9580                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
9581                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9582                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9583                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9584                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9585                         DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9586                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9587                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9588                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9589                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9590                         DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
9591                         DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9592                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9593                         break;
9594                 default:
9595                         break;
9596                 }
9597                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9598                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9599                 break;
9600         case RENDERPATH_GL13:
9601         case RENDERPATH_GL11:
9602                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9603                 {
9604                         // apply a color tint to the whole view
9605                         R_ResetViewRendering2D();
9606                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9607                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9608                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9609                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9610                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9611                 }
9612                 break;
9613         }
9614 }
9615
9616 matrix4x4_t r_waterscrollmatrix;
9617
9618 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9619 {
9620         if (r_refdef.fog_density)
9621         {
9622                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9623                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9624                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9625
9626                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9627                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9628                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9629                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9630
9631                 {
9632                         vec3_t fogvec;
9633                         VectorCopy(r_refdef.fogcolor, fogvec);
9634                         //   color.rgb *= ContrastBoost * SceneBrightness;
9635                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9636                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9637                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9638                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9639                 }
9640         }
9641 }
9642
9643 void R_UpdateVariables(void)
9644 {
9645         R_Textures_Frame();
9646
9647         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9648
9649         r_refdef.farclip = r_farclip_base.value;
9650         if (r_refdef.scene.worldmodel)
9651                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9652         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9653
9654         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9655                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9656         r_refdef.polygonfactor = 0;
9657         r_refdef.polygonoffset = 0;
9658         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9659         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9660
9661         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9662         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9663         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9664         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9665         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9666         if (FAKELIGHT_ENABLED)
9667         {
9668                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9669         }
9670         if (r_showsurfaces.integer)
9671         {
9672                 r_refdef.scene.rtworld = false;
9673                 r_refdef.scene.rtworldshadows = false;
9674                 r_refdef.scene.rtdlight = false;
9675                 r_refdef.scene.rtdlightshadows = false;
9676                 r_refdef.lightmapintensity = 0;
9677         }
9678
9679         if (gamemode == GAME_NEHAHRA)
9680         {
9681                 if (gl_fogenable.integer)
9682                 {
9683                         r_refdef.oldgl_fogenable = true;
9684                         r_refdef.fog_density = gl_fogdensity.value;
9685                         r_refdef.fog_red = gl_fogred.value;
9686                         r_refdef.fog_green = gl_foggreen.value;
9687                         r_refdef.fog_blue = gl_fogblue.value;
9688                         r_refdef.fog_alpha = 1;
9689                         r_refdef.fog_start = 0;
9690                         r_refdef.fog_end = gl_skyclip.value;
9691                         r_refdef.fog_height = 1<<30;
9692                         r_refdef.fog_fadedepth = 128;
9693                 }
9694                 else if (r_refdef.oldgl_fogenable)
9695                 {
9696                         r_refdef.oldgl_fogenable = false;
9697                         r_refdef.fog_density = 0;
9698                         r_refdef.fog_red = 0;
9699                         r_refdef.fog_green = 0;
9700                         r_refdef.fog_blue = 0;
9701                         r_refdef.fog_alpha = 0;
9702                         r_refdef.fog_start = 0;
9703                         r_refdef.fog_end = 0;
9704                         r_refdef.fog_height = 1<<30;
9705                         r_refdef.fog_fadedepth = 128;
9706                 }
9707         }
9708
9709         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9710         r_refdef.fog_start = max(0, r_refdef.fog_start);
9711         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9712
9713         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9714
9715         if (r_refdef.fog_density && r_drawfog.integer)
9716         {
9717                 r_refdef.fogenabled = true;
9718                 // this is the point where the fog reaches 0.9986 alpha, which we
9719                 // consider a good enough cutoff point for the texture
9720                 // (0.9986 * 256 == 255.6)
9721                 if (r_fog_exp2.integer)
9722                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9723                 else
9724                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9725                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9726                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9727                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9728                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9729                         R_BuildFogHeightTexture();
9730                 // fog color was already set
9731                 // update the fog texture
9732                 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)
9733                         R_BuildFogTexture();
9734                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9735                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9736         }
9737         else
9738                 r_refdef.fogenabled = false;
9739
9740         switch(vid.renderpath)
9741         {
9742         case RENDERPATH_GL20:
9743         case RENDERPATH_CGGL:
9744         case RENDERPATH_D3D9:
9745         case RENDERPATH_D3D10:
9746         case RENDERPATH_D3D11:
9747         case RENDERPATH_SOFT:
9748                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9749                 {
9750                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9751                         {
9752                                 // build GLSL gamma texture
9753 #define RAMPWIDTH 256
9754                                 unsigned short ramp[RAMPWIDTH * 3];
9755                                 unsigned char rampbgr[RAMPWIDTH][4];
9756                                 int i;
9757
9758                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9759
9760                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9761                                 for(i = 0; i < RAMPWIDTH; ++i)
9762                                 {
9763                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9764                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9765                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9766                                         rampbgr[i][3] = 0;
9767                                 }
9768                                 if (r_texture_gammaramps)
9769                                 {
9770                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9771                                 }
9772                                 else
9773                                 {
9774                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9775                                 }
9776                         }
9777                 }
9778                 else
9779                 {
9780                         // remove GLSL gamma texture
9781                 }
9782                 break;
9783         case RENDERPATH_GL13:
9784         case RENDERPATH_GL11:
9785                 break;
9786         }
9787 }
9788
9789 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9790 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9791 /*
9792 ================
9793 R_SelectScene
9794 ================
9795 */
9796 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9797         if( scenetype != r_currentscenetype ) {
9798                 // store the old scenetype
9799                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9800                 r_currentscenetype = scenetype;
9801                 // move in the new scene
9802                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9803         }
9804 }
9805
9806 /*
9807 ================
9808 R_GetScenePointer
9809 ================
9810 */
9811 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9812 {
9813         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9814         if( scenetype == r_currentscenetype ) {
9815                 return &r_refdef.scene;
9816         } else {
9817                 return &r_scenes_store[ scenetype ];
9818         }
9819 }
9820
9821 /*
9822 ================
9823 R_RenderView
9824 ================
9825 */
9826 int dpsoftrast_test;
9827 void R_RenderView(void)
9828 {
9829         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9830
9831         dpsoftrast_test = r_test.integer;
9832
9833         if (r_timereport_active)
9834                 R_TimeReport("start");
9835         r_textureframe++; // used only by R_GetCurrentTexture
9836         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9837
9838         if(R_CompileShader_CheckStaticParms())
9839                 R_GLSL_Restart_f();
9840
9841         if (!r_drawentities.integer)
9842                 r_refdef.scene.numentities = 0;
9843
9844         R_AnimCache_ClearCache();
9845         R_FrameData_NewFrame();
9846
9847         /* adjust for stereo display */
9848         if(R_Stereo_Active())
9849         {
9850                 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);
9851                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9852         }
9853
9854         if (r_refdef.view.isoverlay)
9855         {
9856                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9857                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9858                 R_TimeReport("depthclear");
9859
9860                 r_refdef.view.showdebug = false;
9861
9862                 r_waterstate.enabled = false;
9863                 r_waterstate.numwaterplanes = 0;
9864
9865                 R_RenderScene();
9866
9867                 r_refdef.view.matrix = originalmatrix;
9868
9869                 CHECKGLERROR
9870                 return;
9871         }
9872
9873         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9874         {
9875                 r_refdef.view.matrix = originalmatrix;
9876                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9877         }
9878
9879         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9880
9881         R_RenderView_UpdateViewVectors();
9882
9883         R_Shadow_UpdateWorldLightSelection();
9884
9885         R_Bloom_StartFrame();
9886         R_Water_StartFrame();
9887
9888         CHECKGLERROR
9889         if (r_timereport_active)
9890                 R_TimeReport("viewsetup");
9891
9892         R_ResetViewRendering3D();
9893
9894         if (r_refdef.view.clear || r_refdef.fogenabled)
9895         {
9896                 R_ClearScreen(r_refdef.fogenabled);
9897                 if (r_timereport_active)
9898                         R_TimeReport("viewclear");
9899         }
9900         r_refdef.view.clear = true;
9901
9902         // this produces a bloom texture to be used in R_BlendView() later
9903         if (r_hdr.integer && r_bloomstate.bloomwidth)
9904         {
9905                 R_HDR_RenderBloomTexture();
9906                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9907                 r_textureframe++; // used only by R_GetCurrentTexture
9908         }
9909
9910         r_refdef.view.showdebug = true;
9911
9912         R_View_Update();
9913         if (r_timereport_active)
9914                 R_TimeReport("visibility");
9915
9916         r_waterstate.numwaterplanes = 0;
9917         if (r_waterstate.enabled)
9918                 R_RenderWaterPlanes();
9919
9920         R_RenderScene();
9921         r_waterstate.numwaterplanes = 0;
9922
9923         R_BlendView();
9924         if (r_timereport_active)
9925                 R_TimeReport("blendview");
9926
9927         GL_Scissor(0, 0, vid.width, vid.height);
9928         GL_ScissorTest(false);
9929
9930         r_refdef.view.matrix = originalmatrix;
9931
9932         CHECKGLERROR
9933 }
9934
9935 void R_RenderWaterPlanes(void)
9936 {
9937         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9938         {
9939                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9940                 if (r_timereport_active)
9941                         R_TimeReport("waterworld");
9942         }
9943
9944         // don't let sound skip if going slow
9945         if (r_refdef.scene.extraupdate)
9946                 S_ExtraUpdate ();
9947
9948         R_DrawModelsAddWaterPlanes();
9949         if (r_timereport_active)
9950                 R_TimeReport("watermodels");
9951
9952         if (r_waterstate.numwaterplanes)
9953         {
9954                 R_Water_ProcessPlanes();
9955                 if (r_timereport_active)
9956                         R_TimeReport("waterscenes");
9957         }
9958 }
9959
9960 extern void R_DrawLightningBeams (void);
9961 extern void VM_CL_AddPolygonsToMeshQueue (void);
9962 extern void R_DrawPortals (void);
9963 extern cvar_t cl_locs_show;
9964 static void R_DrawLocs(void);
9965 static void R_DrawEntityBBoxes(void);
9966 static void R_DrawModelDecals(void);
9967 extern void R_DrawModelShadows(void);
9968 extern void R_DrawModelShadowMaps(void);
9969 extern cvar_t cl_decals_newsystem;
9970 extern qboolean r_shadow_usingdeferredprepass;
9971 void R_RenderScene(void)
9972 {
9973         qboolean shadowmapping = false;
9974
9975         if (r_timereport_active)
9976                 R_TimeReport("beginscene");
9977
9978         r_refdef.stats.renders++;
9979
9980         R_UpdateFogColor();
9981
9982         // don't let sound skip if going slow
9983         if (r_refdef.scene.extraupdate)
9984                 S_ExtraUpdate ();
9985
9986         R_MeshQueue_BeginScene();
9987
9988         R_SkyStartFrame();
9989
9990         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);
9991
9992         if (r_timereport_active)
9993                 R_TimeReport("skystartframe");
9994
9995         if (cl.csqc_vidvars.drawworld)
9996         {
9997                 // don't let sound skip if going slow
9998                 if (r_refdef.scene.extraupdate)
9999                         S_ExtraUpdate ();
10000
10001                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
10002                 {
10003                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
10004                         if (r_timereport_active)
10005                                 R_TimeReport("worldsky");
10006                 }
10007
10008                 if (R_DrawBrushModelsSky() && r_timereport_active)
10009                         R_TimeReport("bmodelsky");
10010
10011                 if (skyrendermasked && skyrenderlater)
10012                 {
10013                         // we have to force off the water clipping plane while rendering sky
10014                         R_SetupView(false);
10015                         R_Sky();
10016                         R_SetupView(true);
10017                         if (r_timereport_active)
10018                                 R_TimeReport("sky");
10019                 }
10020         }
10021
10022         R_AnimCache_CacheVisibleEntities();
10023         if (r_timereport_active)
10024                 R_TimeReport("animation");
10025
10026         R_Shadow_PrepareLights();
10027         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
10028                 R_Shadow_PrepareModelShadows();
10029         if (r_timereport_active)
10030                 R_TimeReport("preparelights");
10031
10032         if (R_Shadow_ShadowMappingEnabled())
10033                 shadowmapping = true;
10034
10035         if (r_shadow_usingdeferredprepass)
10036                 R_Shadow_DrawPrepass();
10037
10038         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
10039         {
10040                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
10041                 if (r_timereport_active)
10042                         R_TimeReport("worlddepth");
10043         }
10044         if (r_depthfirst.integer >= 2)
10045         {
10046                 R_DrawModelsDepth();
10047                 if (r_timereport_active)
10048                         R_TimeReport("modeldepth");
10049         }
10050
10051         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
10052         {
10053                 R_DrawModelShadowMaps();
10054                 R_ResetViewRendering3D();
10055                 // don't let sound skip if going slow
10056                 if (r_refdef.scene.extraupdate)
10057                         S_ExtraUpdate ();
10058         }
10059
10060         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
10061         {
10062                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
10063                 if (r_timereport_active)
10064                         R_TimeReport("world");
10065         }
10066
10067         // don't let sound skip if going slow
10068         if (r_refdef.scene.extraupdate)
10069                 S_ExtraUpdate ();
10070
10071         R_DrawModels();
10072         if (r_timereport_active)
10073                 R_TimeReport("models");
10074
10075         // don't let sound skip if going slow
10076         if (r_refdef.scene.extraupdate)
10077                 S_ExtraUpdate ();
10078
10079         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10080         {
10081                 R_DrawModelShadows();
10082                 R_ResetViewRendering3D();
10083                 // don't let sound skip if going slow
10084                 if (r_refdef.scene.extraupdate)
10085                         S_ExtraUpdate ();
10086         }
10087
10088         if (!r_shadow_usingdeferredprepass)
10089         {
10090                 R_Shadow_DrawLights();
10091                 if (r_timereport_active)
10092                         R_TimeReport("rtlights");
10093         }
10094
10095         // don't let sound skip if going slow
10096         if (r_refdef.scene.extraupdate)
10097                 S_ExtraUpdate ();
10098
10099         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10100         {
10101                 R_DrawModelShadows();
10102                 R_ResetViewRendering3D();
10103                 // don't let sound skip if going slow
10104                 if (r_refdef.scene.extraupdate)
10105                         S_ExtraUpdate ();
10106         }
10107
10108         if (cl.csqc_vidvars.drawworld)
10109         {
10110                 if (cl_decals_newsystem.integer)
10111                 {
10112                         R_DrawModelDecals();
10113                         if (r_timereport_active)
10114                                 R_TimeReport("modeldecals");
10115                 }
10116                 else
10117                 {
10118                         R_DrawDecals();
10119                         if (r_timereport_active)
10120                                 R_TimeReport("decals");
10121                 }
10122
10123                 R_DrawParticles();
10124                 if (r_timereport_active)
10125                         R_TimeReport("particles");
10126
10127                 R_DrawExplosions();
10128                 if (r_timereport_active)
10129                         R_TimeReport("explosions");
10130
10131                 R_DrawLightningBeams();
10132                 if (r_timereport_active)
10133                         R_TimeReport("lightning");
10134         }
10135
10136         VM_CL_AddPolygonsToMeshQueue();
10137
10138         if (r_refdef.view.showdebug)
10139         {
10140                 if (cl_locs_show.integer)
10141                 {
10142                         R_DrawLocs();
10143                         if (r_timereport_active)
10144                                 R_TimeReport("showlocs");
10145                 }
10146
10147                 if (r_drawportals.integer)
10148                 {
10149                         R_DrawPortals();
10150                         if (r_timereport_active)
10151                                 R_TimeReport("portals");
10152                 }
10153
10154                 if (r_showbboxes.value > 0)
10155                 {
10156                         R_DrawEntityBBoxes();
10157                         if (r_timereport_active)
10158                                 R_TimeReport("bboxes");
10159                 }
10160         }
10161
10162         R_MeshQueue_RenderTransparent();
10163         if (r_timereport_active)
10164                 R_TimeReport("drawtrans");
10165
10166         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))
10167         {
10168                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10169                 if (r_timereport_active)
10170                         R_TimeReport("worlddebug");
10171                 R_DrawModelsDebug();
10172                 if (r_timereport_active)
10173                         R_TimeReport("modeldebug");
10174         }
10175
10176         if (cl.csqc_vidvars.drawworld)
10177         {
10178                 R_Shadow_DrawCoronas();
10179                 if (r_timereport_active)
10180                         R_TimeReport("coronas");
10181         }
10182
10183 #if 0
10184         {
10185                 GL_DepthTest(false);
10186                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10187                 GL_Color(1, 1, 1, 1);
10188                 qglBegin(GL_POLYGON);
10189                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10190                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10191                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10192                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10193                 qglEnd();
10194                 qglBegin(GL_POLYGON);
10195                 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]);
10196                 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]);
10197                 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]);
10198                 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]);
10199                 qglEnd();
10200                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10201         }
10202 #endif
10203
10204         // don't let sound skip if going slow
10205         if (r_refdef.scene.extraupdate)
10206                 S_ExtraUpdate ();
10207
10208         R_ResetViewRendering2D();
10209 }
10210
10211 static const unsigned short bboxelements[36] =
10212 {
10213         5, 1, 3, 5, 3, 7,
10214         6, 2, 0, 6, 0, 4,
10215         7, 3, 2, 7, 2, 6,
10216         4, 0, 1, 4, 1, 5,
10217         4, 5, 7, 4, 7, 6,
10218         1, 0, 2, 1, 2, 3,
10219 };
10220
10221 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10222 {
10223         int i;
10224         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10225
10226         RSurf_ActiveWorldEntity();
10227
10228         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10229         GL_DepthMask(false);
10230         GL_DepthRange(0, 1);
10231         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10232 //      R_Mesh_ResetTextureState();
10233
10234         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10235         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10236         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10237         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10238         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10239         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10240         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10241         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10242         R_FillColors(color4f, 8, cr, cg, cb, ca);
10243         if (r_refdef.fogenabled)
10244         {
10245                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10246                 {
10247                         f1 = RSurf_FogVertex(v);
10248                         f2 = 1 - f1;
10249                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10250                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10251                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10252                 }
10253         }
10254         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10255         R_Mesh_ResetTextureState();
10256         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10257         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10258 }
10259
10260 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10261 {
10262         int i;
10263         float color[4];
10264         prvm_edict_t *edict;
10265         prvm_prog_t *prog_save = prog;
10266
10267         // this function draws bounding boxes of server entities
10268         if (!sv.active)
10269                 return;
10270
10271         GL_CullFace(GL_NONE);
10272         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10273
10274         prog = 0;
10275         SV_VM_Begin();
10276         for (i = 0;i < numsurfaces;i++)
10277         {
10278                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10279                 switch ((int)edict->fields.server->solid)
10280                 {
10281                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10282                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10283                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10284                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10285                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10286                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10287                 }
10288                 color[3] *= r_showbboxes.value;
10289                 color[3] = bound(0, color[3], 1);
10290                 GL_DepthTest(!r_showdisabledepthtest.integer);
10291                 GL_CullFace(r_refdef.view.cullface_front);
10292                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10293         }
10294         SV_VM_End();
10295         prog = prog_save;
10296 }
10297
10298 static void R_DrawEntityBBoxes(void)
10299 {
10300         int i;
10301         prvm_edict_t *edict;
10302         vec3_t center;
10303         prvm_prog_t *prog_save = prog;
10304
10305         // this function draws bounding boxes of server entities
10306         if (!sv.active)
10307                 return;
10308
10309         prog = 0;
10310         SV_VM_Begin();
10311         for (i = 0;i < prog->num_edicts;i++)
10312         {
10313                 edict = PRVM_EDICT_NUM(i);
10314                 if (edict->priv.server->free)
10315                         continue;
10316                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10317                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10318                         continue;
10319                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10320                         continue;
10321                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10322                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10323         }
10324         SV_VM_End();
10325         prog = prog_save;
10326 }
10327
10328 static const int nomodelelement3i[24] =
10329 {
10330         5, 2, 0,
10331         5, 1, 2,
10332         5, 0, 3,
10333         5, 3, 1,
10334         0, 2, 4,
10335         2, 1, 4,
10336         3, 0, 4,
10337         1, 3, 4
10338 };
10339
10340 static const unsigned short nomodelelement3s[24] =
10341 {
10342         5, 2, 0,
10343         5, 1, 2,
10344         5, 0, 3,
10345         5, 3, 1,
10346         0, 2, 4,
10347         2, 1, 4,
10348         3, 0, 4,
10349         1, 3, 4
10350 };
10351
10352 static const float nomodelvertex3f[6*3] =
10353 {
10354         -16,   0,   0,
10355          16,   0,   0,
10356           0, -16,   0,
10357           0,  16,   0,
10358           0,   0, -16,
10359           0,   0,  16
10360 };
10361
10362 static const float nomodelcolor4f[6*4] =
10363 {
10364         0.0f, 0.0f, 0.5f, 1.0f,
10365         0.0f, 0.0f, 0.5f, 1.0f,
10366         0.0f, 0.5f, 0.0f, 1.0f,
10367         0.0f, 0.5f, 0.0f, 1.0f,
10368         0.5f, 0.0f, 0.0f, 1.0f,
10369         0.5f, 0.0f, 0.0f, 1.0f
10370 };
10371
10372 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10373 {
10374         int i;
10375         float f1, f2, *c;
10376         float color4f[6*4];
10377
10378         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);
10379
10380         // this is only called once per entity so numsurfaces is always 1, and
10381         // surfacelist is always {0}, so this code does not handle batches
10382
10383         if (rsurface.ent_flags & RENDER_ADDITIVE)
10384         {
10385                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10386                 GL_DepthMask(false);
10387         }
10388         else if (rsurface.colormod[3] < 1)
10389         {
10390                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10391                 GL_DepthMask(false);
10392         }
10393         else
10394         {
10395                 GL_BlendFunc(GL_ONE, GL_ZERO);
10396                 GL_DepthMask(true);
10397         }
10398         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10399         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10400         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10401         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10402         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10403         for (i = 0, c = color4f;i < 6;i++, c += 4)
10404         {
10405                 c[0] *= rsurface.colormod[0];
10406                 c[1] *= rsurface.colormod[1];
10407                 c[2] *= rsurface.colormod[2];
10408                 c[3] *= rsurface.colormod[3];
10409         }
10410         if (r_refdef.fogenabled)
10411         {
10412                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10413                 {
10414                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10415                         f2 = 1 - f1;
10416                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10417                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10418                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10419                 }
10420         }
10421 //      R_Mesh_ResetTextureState();
10422         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10423         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10424         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10425 }
10426
10427 void R_DrawNoModel(entity_render_t *ent)
10428 {
10429         vec3_t org;
10430         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10431         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10432                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10433         else
10434                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10435 }
10436
10437 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10438 {
10439         vec3_t right1, right2, diff, normal;
10440
10441         VectorSubtract (org2, org1, normal);
10442
10443         // calculate 'right' vector for start
10444         VectorSubtract (r_refdef.view.origin, org1, diff);
10445         CrossProduct (normal, diff, right1);
10446         VectorNormalize (right1);
10447
10448         // calculate 'right' vector for end
10449         VectorSubtract (r_refdef.view.origin, org2, diff);
10450         CrossProduct (normal, diff, right2);
10451         VectorNormalize (right2);
10452
10453         vert[ 0] = org1[0] + width * right1[0];
10454         vert[ 1] = org1[1] + width * right1[1];
10455         vert[ 2] = org1[2] + width * right1[2];
10456         vert[ 3] = org1[0] - width * right1[0];
10457         vert[ 4] = org1[1] - width * right1[1];
10458         vert[ 5] = org1[2] - width * right1[2];
10459         vert[ 6] = org2[0] - width * right2[0];
10460         vert[ 7] = org2[1] - width * right2[1];
10461         vert[ 8] = org2[2] - width * right2[2];
10462         vert[ 9] = org2[0] + width * right2[0];
10463         vert[10] = org2[1] + width * right2[1];
10464         vert[11] = org2[2] + width * right2[2];
10465 }
10466
10467 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)
10468 {
10469         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10470         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10471         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10472         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10473         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10474         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10475         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10476         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10477         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10478         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10479         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10480         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10481 }
10482
10483 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10484 {
10485         int i;
10486         float *vertex3f;
10487         float v[3];
10488         VectorSet(v, x, y, z);
10489         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10490                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10491                         break;
10492         if (i == mesh->numvertices)
10493         {
10494                 if (mesh->numvertices < mesh->maxvertices)
10495                 {
10496                         VectorCopy(v, vertex3f);
10497                         mesh->numvertices++;
10498                 }
10499                 return mesh->numvertices;
10500         }
10501         else
10502                 return i;
10503 }
10504
10505 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10506 {
10507         int i;
10508         int *e, element[3];
10509         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10510         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10511         e = mesh->element3i + mesh->numtriangles * 3;
10512         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10513         {
10514                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10515                 if (mesh->numtriangles < mesh->maxtriangles)
10516                 {
10517                         *e++ = element[0];
10518                         *e++ = element[1];
10519                         *e++ = element[2];
10520                         mesh->numtriangles++;
10521                 }
10522                 element[1] = element[2];
10523         }
10524 }
10525
10526 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10527 {
10528         int i;
10529         int *e, element[3];
10530         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10531         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10532         e = mesh->element3i + mesh->numtriangles * 3;
10533         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10534         {
10535                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10536                 if (mesh->numtriangles < mesh->maxtriangles)
10537                 {
10538                         *e++ = element[0];
10539                         *e++ = element[1];
10540                         *e++ = element[2];
10541                         mesh->numtriangles++;
10542                 }
10543                 element[1] = element[2];
10544         }
10545 }
10546
10547 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10548 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10549 {
10550         int planenum, planenum2;
10551         int w;
10552         int tempnumpoints;
10553         mplane_t *plane, *plane2;
10554         double maxdist;
10555         double temppoints[2][256*3];
10556         // figure out how large a bounding box we need to properly compute this brush
10557         maxdist = 0;
10558         for (w = 0;w < numplanes;w++)
10559                 maxdist = max(maxdist, fabs(planes[w].dist));
10560         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10561         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10562         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10563         {
10564                 w = 0;
10565                 tempnumpoints = 4;
10566                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10567                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10568                 {
10569                         if (planenum2 == planenum)
10570                                 continue;
10571                         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);
10572                         w = !w;
10573                 }
10574                 if (tempnumpoints < 3)
10575                         continue;
10576                 // generate elements forming a triangle fan for this polygon
10577                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10578         }
10579 }
10580
10581 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)
10582 {
10583         texturelayer_t *layer;
10584         layer = t->currentlayers + t->currentnumlayers++;
10585         layer->type = type;
10586         layer->depthmask = depthmask;
10587         layer->blendfunc1 = blendfunc1;
10588         layer->blendfunc2 = blendfunc2;
10589         layer->texture = texture;
10590         layer->texmatrix = *matrix;
10591         layer->color[0] = r;
10592         layer->color[1] = g;
10593         layer->color[2] = b;
10594         layer->color[3] = a;
10595 }
10596
10597 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10598 {
10599         if(parms[0] == 0 && parms[1] == 0)
10600                 return false;
10601         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10602                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10603                         return false;
10604         return true;
10605 }
10606
10607 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10608 {
10609         double index, f;
10610         index = parms[2] + r_refdef.scene.time * parms[3];
10611         index -= floor(index);
10612         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10613         {
10614         default:
10615         case Q3WAVEFUNC_NONE:
10616         case Q3WAVEFUNC_NOISE:
10617         case Q3WAVEFUNC_COUNT:
10618                 f = 0;
10619                 break;
10620         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10621         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10622         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10623         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10624         case Q3WAVEFUNC_TRIANGLE:
10625                 index *= 4;
10626                 f = index - floor(index);
10627                 if (index < 1)
10628                         f = f;
10629                 else if (index < 2)
10630                         f = 1 - f;
10631                 else if (index < 3)
10632                         f = -f;
10633                 else
10634                         f = -(1 - f);
10635                 break;
10636         }
10637         f = parms[0] + parms[1] * f;
10638         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10639                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10640         return (float) f;
10641 }
10642
10643 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10644 {
10645         int w, h, idx;
10646         float f;
10647         float tcmat[12];
10648         matrix4x4_t matrix, temp;
10649         switch(tcmod->tcmod)
10650         {
10651                 case Q3TCMOD_COUNT:
10652                 case Q3TCMOD_NONE:
10653                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10654                                 matrix = r_waterscrollmatrix;
10655                         else
10656                                 matrix = identitymatrix;
10657                         break;
10658                 case Q3TCMOD_ENTITYTRANSLATE:
10659                         // this is used in Q3 to allow the gamecode to control texcoord
10660                         // scrolling on the entity, which is not supported in darkplaces yet.
10661                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10662                         break;
10663                 case Q3TCMOD_ROTATE:
10664                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10665                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10666                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10667                         break;
10668                 case Q3TCMOD_SCALE:
10669                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10670                         break;
10671                 case Q3TCMOD_SCROLL:
10672                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10673                         break;
10674                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10675                         w = (int) tcmod->parms[0];
10676                         h = (int) tcmod->parms[1];
10677                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10678                         f = f - floor(f);
10679                         idx = (int) floor(f * w * h);
10680                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10681                         break;
10682                 case Q3TCMOD_STRETCH:
10683                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10684                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10685                         break;
10686                 case Q3TCMOD_TRANSFORM:
10687                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10688                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10689                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10690                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10691                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10692                         break;
10693                 case Q3TCMOD_TURBULENT:
10694                         // this is handled in the RSurf_PrepareVertices function
10695                         matrix = identitymatrix;
10696                         break;
10697         }
10698         temp = *texmatrix;
10699         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10700 }
10701
10702 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10703 {
10704         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10705         char name[MAX_QPATH];
10706         skinframe_t *skinframe;
10707         unsigned char pixels[296*194];
10708         strlcpy(cache->name, skinname, sizeof(cache->name));
10709         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10710         if (developer_loading.integer)
10711                 Con_Printf("loading %s\n", name);
10712         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10713         if (!skinframe || !skinframe->base)
10714         {
10715                 unsigned char *f;
10716                 fs_offset_t filesize;
10717                 skinframe = NULL;
10718                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10719                 if (f)
10720                 {
10721                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10722                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10723                         Mem_Free(f);
10724                 }
10725         }
10726         cache->skinframe = skinframe;
10727 }
10728
10729 texture_t *R_GetCurrentTexture(texture_t *t)
10730 {
10731         int i;
10732         const entity_render_t *ent = rsurface.entity;
10733         dp_model_t *model = ent->model;
10734         q3shaderinfo_layer_tcmod_t *tcmod;
10735
10736         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10737                 return t->currentframe;
10738         t->update_lastrenderframe = r_textureframe;
10739         t->update_lastrenderentity = (void *)ent;
10740
10741         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10742                 t->camera_entity = ent->entitynumber;
10743         else
10744                 t->camera_entity = 0;
10745
10746         // switch to an alternate material if this is a q1bsp animated material
10747         {
10748                 texture_t *texture = t;
10749                 int s = rsurface.ent_skinnum;
10750                 if ((unsigned int)s >= (unsigned int)model->numskins)
10751                         s = 0;
10752                 if (model->skinscenes)
10753                 {
10754                         if (model->skinscenes[s].framecount > 1)
10755                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10756                         else
10757                                 s = model->skinscenes[s].firstframe;
10758                 }
10759                 if (s > 0)
10760                         t = t + s * model->num_surfaces;
10761                 if (t->animated)
10762                 {
10763                         // use an alternate animation if the entity's frame is not 0,
10764                         // and only if the texture has an alternate animation
10765                         if (rsurface.ent_alttextures && t->anim_total[1])
10766                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10767                         else
10768                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10769                 }
10770                 texture->currentframe = t;
10771         }
10772
10773         // update currentskinframe to be a qw skin or animation frame
10774         if (rsurface.ent_qwskin >= 0)
10775         {
10776                 i = rsurface.ent_qwskin;
10777                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10778                 {
10779                         r_qwskincache_size = cl.maxclients;
10780                         if (r_qwskincache)
10781                                 Mem_Free(r_qwskincache);
10782                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10783                 }
10784                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10785                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10786                 t->currentskinframe = r_qwskincache[i].skinframe;
10787                 if (t->currentskinframe == NULL)
10788                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10789         }
10790         else if (t->numskinframes >= 2)
10791                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10792         if (t->backgroundnumskinframes >= 2)
10793                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10794
10795         t->currentmaterialflags = t->basematerialflags;
10796         t->currentalpha = rsurface.colormod[3];
10797         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10798                 t->currentalpha *= r_wateralpha.value;
10799         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10800                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10801         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10802                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10803         if (!(rsurface.ent_flags & RENDER_LIGHT))
10804                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10805         else if (FAKELIGHT_ENABLED)
10806         {
10807                         // no modellight if using fakelight for the map
10808         }
10809         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10810         {
10811                 // pick a model lighting mode
10812                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10813                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10814                 else
10815                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10816         }
10817         if (rsurface.ent_flags & RENDER_ADDITIVE)
10818                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10819         else if (t->currentalpha < 1)
10820                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10821         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10822                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10823         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10824                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10825         if (t->backgroundnumskinframes)
10826                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10827         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10828         {
10829                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10830                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10831         }
10832         else
10833                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10834         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10835                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10836
10837         // there is no tcmod
10838         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10839         {
10840                 t->currenttexmatrix = r_waterscrollmatrix;
10841                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10842         }
10843         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10844         {
10845                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10846                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10847         }
10848
10849         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10850                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10851         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10852                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10853
10854         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10855         if (t->currentskinframe->qpixels)
10856                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10857         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10858         if (!t->basetexture)
10859                 t->basetexture = r_texture_notexture;
10860         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10861         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10862         t->nmaptexture = t->currentskinframe->nmap;
10863         if (!t->nmaptexture)
10864                 t->nmaptexture = r_texture_blanknormalmap;
10865         t->glosstexture = r_texture_black;
10866         t->glowtexture = t->currentskinframe->glow;
10867         t->fogtexture = t->currentskinframe->fog;
10868         t->reflectmasktexture = t->currentskinframe->reflect;
10869         if (t->backgroundnumskinframes)
10870         {
10871                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10872                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10873                 t->backgroundglosstexture = r_texture_black;
10874                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10875                 if (!t->backgroundnmaptexture)
10876                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10877         }
10878         else
10879         {
10880                 t->backgroundbasetexture = r_texture_white;
10881                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10882                 t->backgroundglosstexture = r_texture_black;
10883                 t->backgroundglowtexture = NULL;
10884         }
10885         t->specularpower = r_shadow_glossexponent.value;
10886         // TODO: store reference values for these in the texture?
10887         t->specularscale = 0;
10888         if (r_shadow_gloss.integer > 0)
10889         {
10890                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10891                 {
10892                         if (r_shadow_glossintensity.value > 0)
10893                         {
10894                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10895                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10896                                 t->specularscale = r_shadow_glossintensity.value;
10897                         }
10898                 }
10899                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10900                 {
10901                         t->glosstexture = r_texture_white;
10902                         t->backgroundglosstexture = r_texture_white;
10903                         t->specularscale = r_shadow_gloss2intensity.value;
10904                         t->specularpower = r_shadow_gloss2exponent.value;
10905                 }
10906         }
10907         t->specularscale *= t->specularscalemod;
10908         t->specularpower *= t->specularpowermod;
10909
10910         // lightmaps mode looks bad with dlights using actual texturing, so turn
10911         // off the colormap and glossmap, but leave the normalmap on as it still
10912         // accurately represents the shading involved
10913         if (gl_lightmaps.integer)
10914         {
10915                 t->basetexture = r_texture_grey128;
10916                 t->pantstexture = r_texture_black;
10917                 t->shirttexture = r_texture_black;
10918                 t->nmaptexture = r_texture_blanknormalmap;
10919                 t->glosstexture = r_texture_black;
10920                 t->glowtexture = NULL;
10921                 t->fogtexture = NULL;
10922                 t->reflectmasktexture = NULL;
10923                 t->backgroundbasetexture = NULL;
10924                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10925                 t->backgroundglosstexture = r_texture_black;
10926                 t->backgroundglowtexture = NULL;
10927                 t->specularscale = 0;
10928                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10929         }
10930
10931         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10932         VectorClear(t->dlightcolor);
10933         t->currentnumlayers = 0;
10934         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10935         {
10936                 int blendfunc1, blendfunc2;
10937                 qboolean depthmask;
10938                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10939                 {
10940                         blendfunc1 = GL_SRC_ALPHA;
10941                         blendfunc2 = GL_ONE;
10942                 }
10943                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10944                 {
10945                         blendfunc1 = GL_SRC_ALPHA;
10946                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10947                 }
10948                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10949                 {
10950                         blendfunc1 = t->customblendfunc[0];
10951                         blendfunc2 = t->customblendfunc[1];
10952                 }
10953                 else
10954                 {
10955                         blendfunc1 = GL_ONE;
10956                         blendfunc2 = GL_ZERO;
10957                 }
10958                 // don't colormod evilblend textures
10959                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10960                         VectorSet(t->lightmapcolor, 1, 1, 1);
10961                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10962                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10963                 {
10964                         // fullbright is not affected by r_refdef.lightmapintensity
10965                         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]);
10966                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10967                                 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]);
10968                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10969                                 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]);
10970                 }
10971                 else
10972                 {
10973                         vec3_t ambientcolor;
10974                         float colorscale;
10975                         // set the color tint used for lights affecting this surface
10976                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10977                         colorscale = 2;
10978                         // q3bsp has no lightmap updates, so the lightstylevalue that
10979                         // would normally be baked into the lightmap must be
10980                         // applied to the color
10981                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10982                         if (model->type == mod_brushq3)
10983                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10984                         colorscale *= r_refdef.lightmapintensity;
10985                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10986                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10987                         // basic lit geometry
10988                         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]);
10989                         // add pants/shirt if needed
10990                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10991                                 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]);
10992                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10993                                 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]);
10994                         // now add ambient passes if needed
10995                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10996                         {
10997                                 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]);
10998                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10999                                         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]);
11000                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
11001                                         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]);
11002                         }
11003                 }
11004                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
11005                         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]);
11006                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
11007                 {
11008                         // if this is opaque use alpha blend which will darken the earlier
11009                         // passes cheaply.
11010                         //
11011                         // if this is an alpha blended material, all the earlier passes
11012                         // were darkened by fog already, so we only need to add the fog
11013                         // color ontop through the fog mask texture
11014                         //
11015                         // if this is an additive blended material, all the earlier passes
11016                         // were darkened by fog already, and we should not add fog color
11017                         // (because the background was not darkened, there is no fog color
11018                         // that was lost behind it).
11019                         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]);
11020                 }
11021         }
11022
11023         return t->currentframe;
11024 }
11025
11026 rsurfacestate_t rsurface;
11027
11028 void RSurf_ActiveWorldEntity(void)
11029 {
11030         dp_model_t *model = r_refdef.scene.worldmodel;
11031         //if (rsurface.entity == r_refdef.scene.worldentity)
11032         //      return;
11033         rsurface.entity = r_refdef.scene.worldentity;
11034         rsurface.skeleton = NULL;
11035         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
11036         rsurface.ent_skinnum = 0;
11037         rsurface.ent_qwskin = -1;
11038         rsurface.ent_shadertime = 0;
11039         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
11040         rsurface.matrix = identitymatrix;
11041         rsurface.inversematrix = identitymatrix;
11042         rsurface.matrixscale = 1;
11043         rsurface.inversematrixscale = 1;
11044         R_EntityMatrix(&identitymatrix);
11045         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
11046         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
11047         rsurface.fograngerecip = r_refdef.fograngerecip;
11048         rsurface.fogheightfade = r_refdef.fogheightfade;
11049         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
11050         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11051         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11052         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11053         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11054         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11055         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11056         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
11057         rsurface.colormod[3] = 1;
11058         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);
11059         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11060         rsurface.frameblend[0].lerp = 1;
11061         rsurface.ent_alttextures = false;
11062         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11063         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11064         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11065         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11066         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11067         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11068         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11069         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11070         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11071         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11072         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11073         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11074         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11075         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11076         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11077         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11078         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11079         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11080         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11081         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11082         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11083         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11084         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11085         rsurface.modelelement3i = model->surfmesh.data_element3i;
11086         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11087         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11088         rsurface.modelelement3s = model->surfmesh.data_element3s;
11089         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11090         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11091         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11092         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11093         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11094         rsurface.modelsurfaces = model->data_surfaces;
11095         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11096         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11097         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11098         rsurface.modelgeneratedvertex = false;
11099         rsurface.batchgeneratedvertex = false;
11100         rsurface.batchfirstvertex = 0;
11101         rsurface.batchnumvertices = 0;
11102         rsurface.batchfirsttriangle = 0;
11103         rsurface.batchnumtriangles = 0;
11104         rsurface.batchvertex3f  = NULL;
11105         rsurface.batchvertex3f_vertexbuffer = NULL;
11106         rsurface.batchvertex3f_bufferoffset = 0;
11107         rsurface.batchsvector3f = NULL;
11108         rsurface.batchsvector3f_vertexbuffer = NULL;
11109         rsurface.batchsvector3f_bufferoffset = 0;
11110         rsurface.batchtvector3f = NULL;
11111         rsurface.batchtvector3f_vertexbuffer = NULL;
11112         rsurface.batchtvector3f_bufferoffset = 0;
11113         rsurface.batchnormal3f  = NULL;
11114         rsurface.batchnormal3f_vertexbuffer = NULL;
11115         rsurface.batchnormal3f_bufferoffset = 0;
11116         rsurface.batchlightmapcolor4f = NULL;
11117         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11118         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11119         rsurface.batchtexcoordtexture2f = NULL;
11120         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11121         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11122         rsurface.batchtexcoordlightmap2f = NULL;
11123         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11124         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11125         rsurface.batchvertexmesh = NULL;
11126         rsurface.batchvertexmeshbuffer = NULL;
11127         rsurface.batchvertex3fbuffer = NULL;
11128         rsurface.batchelement3i = NULL;
11129         rsurface.batchelement3i_indexbuffer = NULL;
11130         rsurface.batchelement3i_bufferoffset = 0;
11131         rsurface.batchelement3s = NULL;
11132         rsurface.batchelement3s_indexbuffer = NULL;
11133         rsurface.batchelement3s_bufferoffset = 0;
11134         rsurface.passcolor4f = NULL;
11135         rsurface.passcolor4f_vertexbuffer = NULL;
11136         rsurface.passcolor4f_bufferoffset = 0;
11137 }
11138
11139 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11140 {
11141         dp_model_t *model = ent->model;
11142         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11143         //      return;
11144         rsurface.entity = (entity_render_t *)ent;
11145         rsurface.skeleton = ent->skeleton;
11146         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11147         rsurface.ent_skinnum = ent->skinnum;
11148         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;
11149         rsurface.ent_shadertime = ent->shadertime;
11150         rsurface.ent_flags = ent->flags;
11151         rsurface.matrix = ent->matrix;
11152         rsurface.inversematrix = ent->inversematrix;
11153         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11154         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11155         R_EntityMatrix(&rsurface.matrix);
11156         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11157         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11158         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11159         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11160         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11161         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11162         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11163         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11164         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11165         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11166         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11167         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11168         rsurface.colormod[3] = ent->alpha;
11169         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11170         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11171         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11172         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11173         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11174         if (ent->model->brush.submodel && !prepass)
11175         {
11176                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11177                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11178         }
11179         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11180         {
11181                 if (ent->animcache_vertex3f)
11182                 {
11183                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11184                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11185                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11186                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11187                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11188                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11189                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
11190                 }
11191                 else if (wanttangents)
11192                 {
11193                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11194                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11195                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11196                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11197                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
11198                         rsurface.modelvertexmesh = NULL;
11199                         rsurface.modelvertexmeshbuffer = NULL;
11200                         rsurface.modelvertex3fbuffer = NULL;
11201                 }
11202                 else if (wantnormals)
11203                 {
11204                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11205                         rsurface.modelsvector3f = NULL;
11206                         rsurface.modeltvector3f = NULL;
11207                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11208                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
11209                         rsurface.modelvertexmesh = NULL;
11210                         rsurface.modelvertexmeshbuffer = NULL;
11211                         rsurface.modelvertex3fbuffer = NULL;
11212                 }
11213                 else
11214                 {
11215                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11216                         rsurface.modelsvector3f = NULL;
11217                         rsurface.modeltvector3f = NULL;
11218                         rsurface.modelnormal3f = NULL;
11219                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
11220                         rsurface.modelvertexmesh = NULL;
11221                         rsurface.modelvertexmeshbuffer = NULL;
11222                         rsurface.modelvertex3fbuffer = NULL;
11223                 }
11224                 rsurface.modelvertex3f_vertexbuffer = 0;
11225                 rsurface.modelvertex3f_bufferoffset = 0;
11226                 rsurface.modelsvector3f_vertexbuffer = 0;
11227                 rsurface.modelsvector3f_bufferoffset = 0;
11228                 rsurface.modeltvector3f_vertexbuffer = 0;
11229                 rsurface.modeltvector3f_bufferoffset = 0;
11230                 rsurface.modelnormal3f_vertexbuffer = 0;
11231                 rsurface.modelnormal3f_bufferoffset = 0;
11232                 rsurface.modelgeneratedvertex = true;
11233         }
11234         else
11235         {
11236                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11237                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11238                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11239                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11240                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11241                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11242                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11243                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11244                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11245                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11246                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11247                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11248                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11249                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11250                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11251                 rsurface.modelgeneratedvertex = false;
11252         }
11253         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11254         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11255         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11256         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11257         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11258         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11259         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11260         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11261         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11262         rsurface.modelelement3i = model->surfmesh.data_element3i;
11263         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11264         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11265         rsurface.modelelement3s = model->surfmesh.data_element3s;
11266         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11267         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11268         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11269         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11270         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11271         rsurface.modelsurfaces = model->data_surfaces;
11272         rsurface.batchgeneratedvertex = false;
11273         rsurface.batchfirstvertex = 0;
11274         rsurface.batchnumvertices = 0;
11275         rsurface.batchfirsttriangle = 0;
11276         rsurface.batchnumtriangles = 0;
11277         rsurface.batchvertex3f  = NULL;
11278         rsurface.batchvertex3f_vertexbuffer = NULL;
11279         rsurface.batchvertex3f_bufferoffset = 0;
11280         rsurface.batchsvector3f = NULL;
11281         rsurface.batchsvector3f_vertexbuffer = NULL;
11282         rsurface.batchsvector3f_bufferoffset = 0;
11283         rsurface.batchtvector3f = NULL;
11284         rsurface.batchtvector3f_vertexbuffer = NULL;
11285         rsurface.batchtvector3f_bufferoffset = 0;
11286         rsurface.batchnormal3f  = NULL;
11287         rsurface.batchnormal3f_vertexbuffer = NULL;
11288         rsurface.batchnormal3f_bufferoffset = 0;
11289         rsurface.batchlightmapcolor4f = NULL;
11290         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11291         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11292         rsurface.batchtexcoordtexture2f = NULL;
11293         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11294         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11295         rsurface.batchtexcoordlightmap2f = NULL;
11296         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11297         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11298         rsurface.batchvertexmesh = NULL;
11299         rsurface.batchvertexmeshbuffer = NULL;
11300         rsurface.batchvertex3fbuffer = NULL;
11301         rsurface.batchelement3i = NULL;
11302         rsurface.batchelement3i_indexbuffer = NULL;
11303         rsurface.batchelement3i_bufferoffset = 0;
11304         rsurface.batchelement3s = NULL;
11305         rsurface.batchelement3s_indexbuffer = NULL;
11306         rsurface.batchelement3s_bufferoffset = 0;
11307         rsurface.passcolor4f = NULL;
11308         rsurface.passcolor4f_vertexbuffer = NULL;
11309         rsurface.passcolor4f_bufferoffset = 0;
11310 }
11311
11312 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)
11313 {
11314         rsurface.entity = r_refdef.scene.worldentity;
11315         rsurface.skeleton = NULL;
11316         rsurface.ent_skinnum = 0;
11317         rsurface.ent_qwskin = -1;
11318         rsurface.ent_shadertime = shadertime;
11319         rsurface.ent_flags = entflags;
11320         rsurface.modelnumvertices = numvertices;
11321         rsurface.modelnumtriangles = numtriangles;
11322         rsurface.matrix = *matrix;
11323         rsurface.inversematrix = *inversematrix;
11324         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11325         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11326         R_EntityMatrix(&rsurface.matrix);
11327         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11328         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11329         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11330         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11331         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11332         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11333         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11334         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11335         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11336         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11337         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11338         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11339         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);
11340         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11341         rsurface.frameblend[0].lerp = 1;
11342         rsurface.ent_alttextures = false;
11343         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11344         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11345         if (wanttangents)
11346         {
11347                 rsurface.modelvertex3f = (float *)vertex3f;
11348                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11349                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11350                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11351         }
11352         else if (wantnormals)
11353         {
11354                 rsurface.modelvertex3f = (float *)vertex3f;
11355                 rsurface.modelsvector3f = NULL;
11356                 rsurface.modeltvector3f = NULL;
11357                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11358         }
11359         else
11360         {
11361                 rsurface.modelvertex3f = (float *)vertex3f;
11362                 rsurface.modelsvector3f = NULL;
11363                 rsurface.modeltvector3f = NULL;
11364                 rsurface.modelnormal3f = NULL;
11365         }
11366         rsurface.modelvertexmesh = NULL;
11367         rsurface.modelvertexmeshbuffer = NULL;
11368         rsurface.modelvertex3fbuffer = NULL;
11369         rsurface.modelvertex3f_vertexbuffer = 0;
11370         rsurface.modelvertex3f_bufferoffset = 0;
11371         rsurface.modelsvector3f_vertexbuffer = 0;
11372         rsurface.modelsvector3f_bufferoffset = 0;
11373         rsurface.modeltvector3f_vertexbuffer = 0;
11374         rsurface.modeltvector3f_bufferoffset = 0;
11375         rsurface.modelnormal3f_vertexbuffer = 0;
11376         rsurface.modelnormal3f_bufferoffset = 0;
11377         rsurface.modelgeneratedvertex = true;
11378         rsurface.modellightmapcolor4f  = (float *)color4f;
11379         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11380         rsurface.modellightmapcolor4f_bufferoffset = 0;
11381         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
11382         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11383         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11384         rsurface.modeltexcoordlightmap2f  = NULL;
11385         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11386         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11387         rsurface.modelelement3i = (int *)element3i;
11388         rsurface.modelelement3i_indexbuffer = NULL;
11389         rsurface.modelelement3i_bufferoffset = 0;
11390         rsurface.modelelement3s = (unsigned short *)element3s;
11391         rsurface.modelelement3s_indexbuffer = NULL;
11392         rsurface.modelelement3s_bufferoffset = 0;
11393         rsurface.modellightmapoffsets = NULL;
11394         rsurface.modelsurfaces = NULL;
11395         rsurface.batchgeneratedvertex = false;
11396         rsurface.batchfirstvertex = 0;
11397         rsurface.batchnumvertices = 0;
11398         rsurface.batchfirsttriangle = 0;
11399         rsurface.batchnumtriangles = 0;
11400         rsurface.batchvertex3f  = NULL;
11401         rsurface.batchvertex3f_vertexbuffer = NULL;
11402         rsurface.batchvertex3f_bufferoffset = 0;
11403         rsurface.batchsvector3f = NULL;
11404         rsurface.batchsvector3f_vertexbuffer = NULL;
11405         rsurface.batchsvector3f_bufferoffset = 0;
11406         rsurface.batchtvector3f = NULL;
11407         rsurface.batchtvector3f_vertexbuffer = NULL;
11408         rsurface.batchtvector3f_bufferoffset = 0;
11409         rsurface.batchnormal3f  = NULL;
11410         rsurface.batchnormal3f_vertexbuffer = NULL;
11411         rsurface.batchnormal3f_bufferoffset = 0;
11412         rsurface.batchlightmapcolor4f = NULL;
11413         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11414         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11415         rsurface.batchtexcoordtexture2f = NULL;
11416         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11417         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11418         rsurface.batchtexcoordlightmap2f = NULL;
11419         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11420         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11421         rsurface.batchvertexmesh = NULL;
11422         rsurface.batchvertexmeshbuffer = NULL;
11423         rsurface.batchvertex3fbuffer = NULL;
11424         rsurface.batchelement3i = NULL;
11425         rsurface.batchelement3i_indexbuffer = NULL;
11426         rsurface.batchelement3i_bufferoffset = 0;
11427         rsurface.batchelement3s = NULL;
11428         rsurface.batchelement3s_indexbuffer = NULL;
11429         rsurface.batchelement3s_bufferoffset = 0;
11430         rsurface.passcolor4f = NULL;
11431         rsurface.passcolor4f_vertexbuffer = NULL;
11432         rsurface.passcolor4f_bufferoffset = 0;
11433
11434         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11435         {
11436                 if ((wantnormals || wanttangents) && !normal3f)
11437                 {
11438                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11439                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11440                 }
11441                 if (wanttangents && !svector3f)
11442                 {
11443                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11444                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11445                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11446                 }
11447         }
11448 }
11449
11450 float RSurf_FogPoint(const float *v)
11451 {
11452         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11453         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11454         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11455         float FogHeightFade = r_refdef.fogheightfade;
11456         float fogfrac;
11457         unsigned int fogmasktableindex;
11458         if (r_refdef.fogplaneviewabove)
11459                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11460         else
11461                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11462         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11463         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11464 }
11465
11466 float RSurf_FogVertex(const float *v)
11467 {
11468         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11469         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11470         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11471         float FogHeightFade = rsurface.fogheightfade;
11472         float fogfrac;
11473         unsigned int fogmasktableindex;
11474         if (r_refdef.fogplaneviewabove)
11475                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11476         else
11477                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11478         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11479         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11480 }
11481
11482 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11483 {
11484         int i;
11485         for (i = 0;i < numelements;i++)
11486                 outelement3i[i] = inelement3i[i] + adjust;
11487 }
11488
11489 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11490 extern cvar_t gl_vbo;
11491 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11492 {
11493         int deformindex;
11494         int firsttriangle;
11495         int numtriangles;
11496         int firstvertex;
11497         int endvertex;
11498         int numvertices;
11499         int surfacefirsttriangle;
11500         int surfacenumtriangles;
11501         int surfacefirstvertex;
11502         int surfaceendvertex;
11503         int surfacenumvertices;
11504         int batchnumvertices;
11505         int batchnumtriangles;
11506         int needsupdate;
11507         int i, j;
11508         qboolean gaps;
11509         qboolean dynamicvertex;
11510         float amplitude;
11511         float animpos;
11512         float scale;
11513         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11514         float waveparms[4];
11515         q3shaderinfo_deform_t *deform;
11516         const msurface_t *surface, *firstsurface;
11517         r_vertexmesh_t *vertexmesh;
11518         if (!texturenumsurfaces)
11519                 return;
11520         // find vertex range of this surface batch
11521         gaps = false;
11522         firstsurface = texturesurfacelist[0];
11523         firsttriangle = firstsurface->num_firsttriangle;
11524         batchnumvertices = 0;
11525         batchnumtriangles = 0;
11526         firstvertex = endvertex = firstsurface->num_firstvertex;
11527         for (i = 0;i < texturenumsurfaces;i++)
11528         {
11529                 surface = texturesurfacelist[i];
11530                 if (surface != firstsurface + i)
11531                         gaps = true;
11532                 surfacefirstvertex = surface->num_firstvertex;
11533                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11534                 surfacenumvertices = surface->num_vertices;
11535                 surfacenumtriangles = surface->num_triangles;
11536                 if (firstvertex > surfacefirstvertex)
11537                         firstvertex = surfacefirstvertex;
11538                 if (endvertex < surfaceendvertex)
11539                         endvertex = surfaceendvertex;
11540                 batchnumvertices += surfacenumvertices;
11541                 batchnumtriangles += surfacenumtriangles;
11542         }
11543
11544         // we now know the vertex range used, and if there are any gaps in it
11545         rsurface.batchfirstvertex = firstvertex;
11546         rsurface.batchnumvertices = endvertex - firstvertex;
11547         rsurface.batchfirsttriangle = firsttriangle;
11548         rsurface.batchnumtriangles = batchnumtriangles;
11549
11550         // this variable holds flags for which properties have been updated that
11551         // may require regenerating vertexmesh array...
11552         needsupdate = 0;
11553
11554         // check if any dynamic vertex processing must occur
11555         dynamicvertex = false;
11556
11557         // if there is a chance of animated vertex colors, it's a dynamic batch
11558         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11559         {
11560                 dynamicvertex = true;
11561                 batchneed |= BATCHNEED_NOGAPS;
11562                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
11563         }
11564
11565         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11566         {
11567                 switch (deform->deform)
11568                 {
11569                 default:
11570                 case Q3DEFORM_PROJECTIONSHADOW:
11571                 case Q3DEFORM_TEXT0:
11572                 case Q3DEFORM_TEXT1:
11573                 case Q3DEFORM_TEXT2:
11574                 case Q3DEFORM_TEXT3:
11575                 case Q3DEFORM_TEXT4:
11576                 case Q3DEFORM_TEXT5:
11577                 case Q3DEFORM_TEXT6:
11578                 case Q3DEFORM_TEXT7:
11579                 case Q3DEFORM_NONE:
11580                         break;
11581                 case Q3DEFORM_AUTOSPRITE:
11582                         dynamicvertex = true;
11583                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11584                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11585                         break;
11586                 case Q3DEFORM_AUTOSPRITE2:
11587                         dynamicvertex = true;
11588                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11589                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11590                         break;
11591                 case Q3DEFORM_NORMAL:
11592                         dynamicvertex = true;
11593                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11594                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11595                         break;
11596                 case Q3DEFORM_WAVE:
11597                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11598                                 break; // if wavefunc is a nop, ignore this transform
11599                         dynamicvertex = true;
11600                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11601                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11602                         break;
11603                 case Q3DEFORM_BULGE:
11604                         dynamicvertex = true;
11605                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11606                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11607                         break;
11608                 case Q3DEFORM_MOVE:
11609                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11610                                 break; // if wavefunc is a nop, ignore this transform
11611                         dynamicvertex = true;
11612                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11613                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11614                         break;
11615                 }
11616         }
11617         switch(rsurface.texture->tcgen.tcgen)
11618         {
11619         default:
11620         case Q3TCGEN_TEXTURE:
11621                 break;
11622         case Q3TCGEN_LIGHTMAP:
11623                 dynamicvertex = true;
11624                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11625                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11626                 break;
11627         case Q3TCGEN_VECTOR:
11628                 dynamicvertex = true;
11629                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11630                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11631                 break;
11632         case Q3TCGEN_ENVIRONMENT:
11633                 dynamicvertex = true;
11634                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11635                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11636                 break;
11637         }
11638         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11639         {
11640                 dynamicvertex = true;
11641                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11642                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11643         }
11644
11645         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11646         {
11647                 dynamicvertex = true;
11648                 batchneed |= BATCHNEED_NOGAPS;
11649                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11650         }
11651
11652         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11653         {
11654                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11655                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11656                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11657                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11658                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11659                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11660                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11661         }
11662
11663         // when the model data has no vertex buffer (dynamic mesh), we need to
11664         // eliminate gaps
11665         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11666                 batchneed |= BATCHNEED_NOGAPS;
11667
11668         // if needsupdate, we have to do a dynamic vertex batch for sure
11669         if (needsupdate & batchneed)
11670                 dynamicvertex = true;
11671
11672         // see if we need to build vertexmesh from arrays
11673         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11674                 dynamicvertex = true;
11675
11676         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11677         // also some drivers strongly dislike firstvertex
11678         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11679                 dynamicvertex = true;
11680
11681         rsurface.batchvertex3f = rsurface.modelvertex3f;
11682         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11683         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11684         rsurface.batchsvector3f = rsurface.modelsvector3f;
11685         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11686         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11687         rsurface.batchtvector3f = rsurface.modeltvector3f;
11688         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11689         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11690         rsurface.batchnormal3f = rsurface.modelnormal3f;
11691         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11692         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11693         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11694         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11695         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11696         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11697         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11698         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11699         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11700         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11701         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11702         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11703         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11704         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11705         rsurface.batchelement3i = rsurface.modelelement3i;
11706         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11707         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11708         rsurface.batchelement3s = rsurface.modelelement3s;
11709         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11710         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11711
11712         // if any dynamic vertex processing has to occur in software, we copy the
11713         // entire surface list together before processing to rebase the vertices
11714         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11715         //
11716         // if any gaps exist and we do not have a static vertex buffer, we have to
11717         // copy the surface list together to avoid wasting upload bandwidth on the
11718         // vertices in the gaps.
11719         //
11720         // if gaps exist and we have a static vertex buffer, we still have to
11721         // combine the index buffer ranges into one dynamic index buffer.
11722         //
11723         // in all cases we end up with data that can be drawn in one call.
11724
11725         if (!dynamicvertex)
11726         {
11727                 // static vertex data, just set pointers...
11728                 rsurface.batchgeneratedvertex = false;
11729                 // if there are gaps, we want to build a combined index buffer,
11730                 // otherwise use the original static buffer with an appropriate offset
11731                 if (gaps)
11732                 {
11733                         // build a new triangle elements array for this batch
11734                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11735                         rsurface.batchfirsttriangle = 0;
11736                         numtriangles = 0;
11737                         for (i = 0;i < texturenumsurfaces;i++)
11738                         {
11739                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11740                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11741                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11742                                 numtriangles += surfacenumtriangles;
11743                         }
11744                         rsurface.batchelement3i_indexbuffer = NULL;
11745                         rsurface.batchelement3i_bufferoffset = 0;
11746                         rsurface.batchelement3s = NULL;
11747                         rsurface.batchelement3s_indexbuffer = NULL;
11748                         rsurface.batchelement3s_bufferoffset = 0;
11749                         if (endvertex <= 65536)
11750                         {
11751                                 // make a 16bit (unsigned short) index array if possible
11752                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11753                                 for (i = 0;i < numtriangles*3;i++)
11754                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11755                         }
11756                 }
11757                 return;
11758         }
11759
11760         // something needs software processing, do it for real...
11761         // we only directly handle separate array data in this case and then
11762         // generate interleaved data if needed...
11763         rsurface.batchgeneratedvertex = true;
11764
11765         // now copy the vertex data into a combined array and make an index array
11766         // (this is what Quake3 does all the time)
11767         //if (gaps || rsurface.batchfirstvertex)
11768         {
11769                 rsurface.batchvertex3fbuffer = NULL;
11770                 rsurface.batchvertexmesh = NULL;
11771                 rsurface.batchvertexmeshbuffer = NULL;
11772                 rsurface.batchvertex3f = NULL;
11773                 rsurface.batchvertex3f_vertexbuffer = NULL;
11774                 rsurface.batchvertex3f_bufferoffset = 0;
11775                 rsurface.batchsvector3f = NULL;
11776                 rsurface.batchsvector3f_vertexbuffer = NULL;
11777                 rsurface.batchsvector3f_bufferoffset = 0;
11778                 rsurface.batchtvector3f = NULL;
11779                 rsurface.batchtvector3f_vertexbuffer = NULL;
11780                 rsurface.batchtvector3f_bufferoffset = 0;
11781                 rsurface.batchnormal3f = NULL;
11782                 rsurface.batchnormal3f_vertexbuffer = NULL;
11783                 rsurface.batchnormal3f_bufferoffset = 0;
11784                 rsurface.batchlightmapcolor4f = NULL;
11785                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11786                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11787                 rsurface.batchtexcoordtexture2f = NULL;
11788                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11789                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11790                 rsurface.batchtexcoordlightmap2f = NULL;
11791                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11792                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11793                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11794                 rsurface.batchelement3i_indexbuffer = NULL;
11795                 rsurface.batchelement3i_bufferoffset = 0;
11796                 rsurface.batchelement3s = NULL;
11797                 rsurface.batchelement3s_indexbuffer = NULL;
11798                 rsurface.batchelement3s_bufferoffset = 0;
11799                 // we'll only be setting up certain arrays as needed
11800                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11801                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11802                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11803                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11804                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11805                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11806                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11807                 {
11808                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11809                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11810                 }
11811                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11812                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11813                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11814                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11815                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11816                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11817                 numvertices = 0;
11818                 numtriangles = 0;
11819                 for (i = 0;i < texturenumsurfaces;i++)
11820                 {
11821                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11822                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11823                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11824                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11825                         // copy only the data requested
11826                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11827                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11828                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11829                         {
11830                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11831                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11832                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11833                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11834                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11835                                 {
11836                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11837                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11838                                 }
11839                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11840                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11841                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11842                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11843                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11844                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11845                         }
11846                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11847                         numvertices += surfacenumvertices;
11848                         numtriangles += surfacenumtriangles;
11849                 }
11850
11851                 // generate a 16bit index array as well if possible
11852                 // (in general, dynamic batches fit)
11853                 if (numvertices <= 65536)
11854                 {
11855                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11856                         for (i = 0;i < numtriangles*3;i++)
11857                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11858                 }
11859
11860                 // since we've copied everything, the batch now starts at 0
11861                 rsurface.batchfirstvertex = 0;
11862                 rsurface.batchnumvertices = batchnumvertices;
11863                 rsurface.batchfirsttriangle = 0;
11864                 rsurface.batchnumtriangles = batchnumtriangles;
11865         }
11866
11867         // q1bsp surfaces rendered in vertex color mode have to have colors
11868         // calculated based on lightstyles
11869         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11870         {
11871                 // generate color arrays for the surfaces in this list
11872                 int c[4];
11873                 int scale;
11874                 int size3;
11875                 const int *offsets;
11876                 const unsigned char *lm;
11877                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11878                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11879                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11880                 numvertices = 0;
11881                 for (i = 0;i < texturenumsurfaces;i++)
11882                 {
11883                         surface = texturesurfacelist[i];
11884                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11885                         surfacenumvertices = surface->num_vertices;
11886                         if (surface->lightmapinfo->samples)
11887                         {
11888                                 for (j = 0;j < surfacenumvertices;j++)
11889                                 {
11890                                         lm = surface->lightmapinfo->samples + offsets[j];
11891                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11892                                         VectorScale(lm, scale, c);
11893                                         if (surface->lightmapinfo->styles[1] != 255)
11894                                         {
11895                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11896                                                 lm += size3;
11897                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11898                                                 VectorMA(c, scale, lm, c);
11899                                                 if (surface->lightmapinfo->styles[2] != 255)
11900                                                 {
11901                                                         lm += size3;
11902                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11903                                                         VectorMA(c, scale, lm, c);
11904                                                         if (surface->lightmapinfo->styles[3] != 255)
11905                                                         {
11906                                                                 lm += size3;
11907                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11908                                                                 VectorMA(c, scale, lm, c);
11909                                                         }
11910                                                 }
11911                                         }
11912                                         c[0] >>= 15;
11913                                         c[1] >>= 15;
11914                                         c[2] >>= 15;
11915                                         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);
11916                                         numvertices++;
11917                                 }
11918                         }
11919                         else
11920                         {
11921                                 for (j = 0;j < surfacenumvertices;j++)
11922                                 {
11923                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11924                                         numvertices++;
11925                                 }
11926                         }
11927                 }
11928         }
11929
11930         // if vertices are deformed (sprite flares and things in maps, possibly
11931         // water waves, bulges and other deformations), modify the copied vertices
11932         // in place
11933         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11934         {
11935                 switch (deform->deform)
11936                 {
11937                 default:
11938                 case Q3DEFORM_PROJECTIONSHADOW:
11939                 case Q3DEFORM_TEXT0:
11940                 case Q3DEFORM_TEXT1:
11941                 case Q3DEFORM_TEXT2:
11942                 case Q3DEFORM_TEXT3:
11943                 case Q3DEFORM_TEXT4:
11944                 case Q3DEFORM_TEXT5:
11945                 case Q3DEFORM_TEXT6:
11946                 case Q3DEFORM_TEXT7:
11947                 case Q3DEFORM_NONE:
11948                         break;
11949                 case Q3DEFORM_AUTOSPRITE:
11950                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11951                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11952                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11953                         VectorNormalize(newforward);
11954                         VectorNormalize(newright);
11955                         VectorNormalize(newup);
11956 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11957 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11958 //                      rsurface.batchvertex3f_bufferoffset = 0;
11959 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11960 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
11961 //                      rsurface.batchsvector3f_bufferoffset = 0;
11962 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11963 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
11964 //                      rsurface.batchtvector3f_bufferoffset = 0;
11965 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11966 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11967 //                      rsurface.batchnormal3f_bufferoffset = 0;
11968                         // a single autosprite surface can contain multiple sprites...
11969                         for (j = 0;j < batchnumvertices - 3;j += 4)
11970                         {
11971                                 VectorClear(center);
11972                                 for (i = 0;i < 4;i++)
11973                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11974                                 VectorScale(center, 0.25f, center);
11975                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11976                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11977                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11978                                 for (i = 0;i < 4;i++)
11979                                 {
11980                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11981                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11982                                 }
11983                         }
11984                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11985                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11986                         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);
11987                         break;
11988                 case Q3DEFORM_AUTOSPRITE2:
11989                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11990                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11991                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11992                         VectorNormalize(newforward);
11993                         VectorNormalize(newright);
11994                         VectorNormalize(newup);
11995 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11996 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11997 //                      rsurface.batchvertex3f_bufferoffset = 0;
11998                         {
11999                                 const float *v1, *v2;
12000                                 vec3_t start, end;
12001                                 float f, l;
12002                                 struct
12003                                 {
12004                                         float length2;
12005                                         const float *v1;
12006                                         const float *v2;
12007                                 }
12008                                 shortest[2];
12009                                 memset(shortest, 0, sizeof(shortest));
12010                                 // a single autosprite surface can contain multiple sprites...
12011                                 for (j = 0;j < batchnumvertices - 3;j += 4)
12012                                 {
12013                                         VectorClear(center);
12014                                         for (i = 0;i < 4;i++)
12015                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
12016                                         VectorScale(center, 0.25f, center);
12017                                         // find the two shortest edges, then use them to define the
12018                                         // axis vectors for rotating around the central axis
12019                                         for (i = 0;i < 6;i++)
12020                                         {
12021                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
12022                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
12023                                                 l = VectorDistance2(v1, v2);
12024                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
12025                                                 if (v1[2] != v2[2])
12026                                                         l += (1.0f / 1024.0f);
12027                                                 if (shortest[0].length2 > l || i == 0)
12028                                                 {
12029                                                         shortest[1] = shortest[0];
12030                                                         shortest[0].length2 = l;
12031                                                         shortest[0].v1 = v1;
12032                                                         shortest[0].v2 = v2;
12033                                                 }
12034                                                 else if (shortest[1].length2 > l || i == 1)
12035                                                 {
12036                                                         shortest[1].length2 = l;
12037                                                         shortest[1].v1 = v1;
12038                                                         shortest[1].v2 = v2;
12039                                                 }
12040                                         }
12041                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
12042                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
12043                                         // this calculates the right vector from the shortest edge
12044                                         // and the up vector from the edge midpoints
12045                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
12046                                         VectorNormalize(right);
12047                                         VectorSubtract(end, start, up);
12048                                         VectorNormalize(up);
12049                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
12050                                         VectorSubtract(rsurface.localvieworigin, center, forward);
12051                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
12052                                         VectorNegate(forward, forward);
12053                                         VectorReflect(forward, 0, up, forward);
12054                                         VectorNormalize(forward);
12055                                         CrossProduct(up, forward, newright);
12056                                         VectorNormalize(newright);
12057                                         // rotate the quad around the up axis vector, this is made
12058                                         // especially easy by the fact we know the quad is flat,
12059                                         // so we only have to subtract the center position and
12060                                         // measure distance along the right vector, and then
12061                                         // multiply that by the newright vector and add back the
12062                                         // center position
12063                                         // we also need to subtract the old position to undo the
12064                                         // displacement from the center, which we do with a
12065                                         // DotProduct, the subtraction/addition of center is also
12066                                         // optimized into DotProducts here
12067                                         l = DotProduct(right, center);
12068                                         for (i = 0;i < 4;i++)
12069                                         {
12070                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
12071                                                 f = DotProduct(right, v1) - l;
12072                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
12073                                         }
12074                                 }
12075                         }
12076                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
12077                         {
12078 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12079 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
12080 //                              rsurface.batchnormal3f_bufferoffset = 0;
12081                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12082                         }
12083                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12084                         {
12085 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12086 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12087 //                              rsurface.batchsvector3f_bufferoffset = 0;
12088 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12089 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12090 //                              rsurface.batchtvector3f_bufferoffset = 0;
12091                                 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);
12092                         }
12093                         break;
12094                 case Q3DEFORM_NORMAL:
12095                         // deform the normals to make reflections wavey
12096                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12097                         rsurface.batchnormal3f_vertexbuffer = NULL;
12098                         rsurface.batchnormal3f_bufferoffset = 0;
12099                         for (j = 0;j < batchnumvertices;j++)
12100                         {
12101                                 float vertex[3];
12102                                 float *normal = rsurface.batchnormal3f + 3*j;
12103                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
12104                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
12105                                 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]);
12106                                 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]);
12107                                 VectorNormalize(normal);
12108                         }
12109                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12110                         {
12111 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12112 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12113 //                              rsurface.batchsvector3f_bufferoffset = 0;
12114 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12115 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12116 //                              rsurface.batchtvector3f_bufferoffset = 0;
12117                                 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);
12118                         }
12119                         break;
12120                 case Q3DEFORM_WAVE:
12121                         // deform vertex array to make wavey water and flags and such
12122                         waveparms[0] = deform->waveparms[0];
12123                         waveparms[1] = deform->waveparms[1];
12124                         waveparms[2] = deform->waveparms[2];
12125                         waveparms[3] = deform->waveparms[3];
12126                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12127                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12128                         // this is how a divisor of vertex influence on deformation
12129                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12130                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12131 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12132 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12133 //                      rsurface.batchvertex3f_bufferoffset = 0;
12134 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12135 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12136 //                      rsurface.batchnormal3f_bufferoffset = 0;
12137                         for (j = 0;j < batchnumvertices;j++)
12138                         {
12139                                 // if the wavefunc depends on time, evaluate it per-vertex
12140                                 if (waveparms[3])
12141                                 {
12142                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12143                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12144                                 }
12145                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12146                         }
12147                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12148                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12149                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12150                         {
12151 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12152 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12153 //                              rsurface.batchsvector3f_bufferoffset = 0;
12154 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12155 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12156 //                              rsurface.batchtvector3f_bufferoffset = 0;
12157                                 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);
12158                         }
12159                         break;
12160                 case Q3DEFORM_BULGE:
12161                         // deform vertex array to make the surface have moving bulges
12162 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12163 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12164 //                      rsurface.batchvertex3f_bufferoffset = 0;
12165 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12166 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12167 //                      rsurface.batchnormal3f_bufferoffset = 0;
12168                         for (j = 0;j < batchnumvertices;j++)
12169                         {
12170                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12171                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12172                         }
12173                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12174                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12175                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12176                         {
12177 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12178 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12179 //                              rsurface.batchsvector3f_bufferoffset = 0;
12180 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12181 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12182 //                              rsurface.batchtvector3f_bufferoffset = 0;
12183                                 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);
12184                         }
12185                         break;
12186                 case Q3DEFORM_MOVE:
12187                         // deform vertex array
12188                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12189                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12190                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12191                         VectorScale(deform->parms, scale, waveparms);
12192 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12193 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12194 //                      rsurface.batchvertex3f_bufferoffset = 0;
12195                         for (j = 0;j < batchnumvertices;j++)
12196                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
12197                         break;
12198                 }
12199         }
12200
12201         // generate texcoords based on the chosen texcoord source
12202         switch(rsurface.texture->tcgen.tcgen)
12203         {
12204         default:
12205         case Q3TCGEN_TEXTURE:
12206                 break;
12207         case Q3TCGEN_LIGHTMAP:
12208 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12209 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12210 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12211                 if (rsurface.batchtexcoordlightmap2f)
12212                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
12213                 break;
12214         case Q3TCGEN_VECTOR:
12215 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12216 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12217 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12218                 for (j = 0;j < batchnumvertices;j++)
12219                 {
12220                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12221                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12222                 }
12223                 break;
12224         case Q3TCGEN_ENVIRONMENT:
12225                 // make environment reflections using a spheremap
12226 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12227 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12228 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12229                 for (j = 0;j < batchnumvertices;j++)
12230                 {
12231                         // identical to Q3A's method, but executed in worldspace so
12232                         // carried models can be shiny too
12233
12234                         float viewer[3], d, reflected[3], worldreflected[3];
12235
12236                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12237                         // VectorNormalize(viewer);
12238
12239                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12240
12241                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12242                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12243                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12244                         // note: this is proportinal to viewer, so we can normalize later
12245
12246                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12247                         VectorNormalize(worldreflected);
12248
12249                         // note: this sphere map only uses world x and z!
12250                         // so positive and negative y will LOOK THE SAME.
12251                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12252                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12253                 }
12254                 break;
12255         }
12256         // the only tcmod that needs software vertex processing is turbulent, so
12257         // check for it here and apply the changes if needed
12258         // and we only support that as the first one
12259         // (handling a mixture of turbulent and other tcmods would be problematic
12260         //  without punting it entirely to a software path)
12261         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12262         {
12263                 amplitude = rsurface.texture->tcmods[0].parms[1];
12264                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12265 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12266 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12267 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12268                 for (j = 0;j < batchnumvertices;j++)
12269                 {
12270                         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);
12271                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12272                 }
12273         }
12274
12275         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12276         {
12277                 // convert the modified arrays to vertex structs
12278 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
12279 //              rsurface.batchvertexmeshbuffer = NULL;
12280                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12281                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12282                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12283                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12284                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12285                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12286                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12287                 {
12288                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12289                         {
12290                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12291                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12292                         }
12293                 }
12294                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12295                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12296                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12297                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12298                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12299                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12300                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12301                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12302                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12303         }
12304 }
12305
12306 void RSurf_DrawBatch(void)
12307 {
12308         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12309         // through the pipeline, killing it earlier in the pipeline would have
12310         // per-surface overhead rather than per-batch overhead, so it's best to
12311         // reject it here, before it hits glDraw.
12312         if (rsurface.batchnumtriangles == 0)
12313                 return;
12314 #if 0
12315         // batch debugging code
12316         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12317         {
12318                 int i;
12319                 int j;
12320                 int c;
12321                 const int *e;
12322                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12323                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12324                 {
12325                         c = e[i];
12326                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12327                         {
12328                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12329                                 {
12330                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12331                                                 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);
12332                                         break;
12333                                 }
12334                         }
12335                 }
12336         }
12337 #endif
12338         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);
12339 }
12340
12341 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12342 {
12343         // pick the closest matching water plane
12344         int planeindex, vertexindex, bestplaneindex = -1;
12345         float d, bestd;
12346         vec3_t vert;
12347         const float *v;
12348         r_waterstate_waterplane_t *p;
12349         qboolean prepared = false;
12350         bestd = 0;
12351         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12352         {
12353                 if(p->camera_entity != rsurface.texture->camera_entity)
12354                         continue;
12355                 d = 0;
12356                 if(!prepared)
12357                 {
12358                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12359                         prepared = true;
12360                         if(rsurface.batchnumvertices == 0)
12361                                 break;
12362                 }
12363                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12364                 {
12365                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12366                         d += fabs(PlaneDiff(vert, &p->plane));
12367                 }
12368                 if (bestd > d || bestplaneindex < 0)
12369                 {
12370                         bestd = d;
12371                         bestplaneindex = planeindex;
12372                 }
12373         }
12374         return bestplaneindex;
12375         // NOTE: this MAY return a totally unrelated water plane; we can ignore
12376         // this situation though, as it might be better to render single larger
12377         // batches with useless stuff (backface culled for example) than to
12378         // render multiple smaller batches
12379 }
12380
12381 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12382 {
12383         int i;
12384         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12385         rsurface.passcolor4f_vertexbuffer = 0;
12386         rsurface.passcolor4f_bufferoffset = 0;
12387         for (i = 0;i < rsurface.batchnumvertices;i++)
12388                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12389 }
12390
12391 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12392 {
12393         int i;
12394         float f;
12395         const float *v;
12396         const float *c;
12397         float *c2;
12398         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12399         rsurface.passcolor4f_vertexbuffer = 0;
12400         rsurface.passcolor4f_bufferoffset = 0;
12401         if (rsurface.passcolor4f)
12402         {
12403                 // generate color arrays
12404                 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)
12405                 {
12406                         f = RSurf_FogVertex(v);
12407                         c2[0] = c[0] * f;
12408                         c2[1] = c[1] * f;
12409                         c2[2] = c[2] * f;
12410                         c2[3] = c[3];
12411                 }
12412         }
12413         else
12414         {
12415                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12416                 {
12417                         f = RSurf_FogVertex(v);
12418                         c2[0] = f;
12419                         c2[1] = f;
12420                         c2[2] = f;
12421                         c2[3] = 1;
12422                 }
12423         }
12424 }
12425
12426 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12427 {
12428         int i;
12429         float f;
12430         const float *v;
12431         const float *c;
12432         float *c2;
12433         if (!rsurface.passcolor4f)
12434                 return;
12435         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12436         rsurface.passcolor4f_vertexbuffer = 0;
12437         rsurface.passcolor4f_bufferoffset = 0;
12438         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)
12439         {
12440                 f = RSurf_FogVertex(v);
12441                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12442                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12443                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12444                 c2[3] = c[3];
12445         }
12446 }
12447
12448 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12449 {
12450         int i;
12451         const float *c;
12452         float *c2;
12453         if (!rsurface.passcolor4f)
12454                 return;
12455         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12456         rsurface.passcolor4f_vertexbuffer = 0;
12457         rsurface.passcolor4f_bufferoffset = 0;
12458         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12459         {
12460                 c2[0] = c[0] * r;
12461                 c2[1] = c[1] * g;
12462                 c2[2] = c[2] * b;
12463                 c2[3] = c[3] * a;
12464         }
12465 }
12466
12467 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12468 {
12469         int i;
12470         const float *c;
12471         float *c2;
12472         if (!rsurface.passcolor4f)
12473                 return;
12474         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12475         rsurface.passcolor4f_vertexbuffer = 0;
12476         rsurface.passcolor4f_bufferoffset = 0;
12477         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12478         {
12479                 c2[0] = c[0] + r_refdef.scene.ambient;
12480                 c2[1] = c[1] + r_refdef.scene.ambient;
12481                 c2[2] = c[2] + r_refdef.scene.ambient;
12482                 c2[3] = c[3];
12483         }
12484 }
12485
12486 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12487 {
12488         // TODO: optimize
12489         rsurface.passcolor4f = NULL;
12490         rsurface.passcolor4f_vertexbuffer = 0;
12491         rsurface.passcolor4f_bufferoffset = 0;
12492         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12493         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12494         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12495         GL_Color(r, g, b, a);
12496         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12497         RSurf_DrawBatch();
12498 }
12499
12500 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12501 {
12502         // TODO: optimize applyfog && applycolor case
12503         // just apply fog if necessary, and tint the fog color array if necessary
12504         rsurface.passcolor4f = NULL;
12505         rsurface.passcolor4f_vertexbuffer = 0;
12506         rsurface.passcolor4f_bufferoffset = 0;
12507         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12508         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12509         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12510         GL_Color(r, g, b, a);
12511         RSurf_DrawBatch();
12512 }
12513
12514 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12515 {
12516         // TODO: optimize
12517         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12518         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12519         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12520         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12521         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12522         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12523         GL_Color(r, g, b, a);
12524         RSurf_DrawBatch();
12525 }
12526
12527 static void RSurf_DrawBatch_GL11_ClampColor(void)
12528 {
12529         int i;
12530         const float *c1;
12531         float *c2;
12532         if (!rsurface.passcolor4f)
12533                 return;
12534         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12535         {
12536                 c2[0] = bound(0.0f, c1[0], 1.0f);
12537                 c2[1] = bound(0.0f, c1[1], 1.0f);
12538                 c2[2] = bound(0.0f, c1[2], 1.0f);
12539                 c2[3] = bound(0.0f, c1[3], 1.0f);
12540         }
12541 }
12542
12543 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12544 {
12545         int i;
12546         float f;
12547         const float *v;
12548         const float *n;
12549         float *c;
12550         //vec3_t eyedir;
12551
12552         // fake shading
12553         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12554         rsurface.passcolor4f_vertexbuffer = 0;
12555         rsurface.passcolor4f_bufferoffset = 0;
12556         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)
12557         {
12558                 f = -DotProduct(r_refdef.view.forward, n);
12559                 f = max(0, f);
12560                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12561                 f *= r_refdef.lightmapintensity;
12562                 Vector4Set(c, f, f, f, 1);
12563         }
12564 }
12565
12566 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12567 {
12568         RSurf_DrawBatch_GL11_ApplyFakeLight();
12569         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12570         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12571         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12572         GL_Color(r, g, b, a);
12573         RSurf_DrawBatch();
12574 }
12575
12576 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12577 {
12578         int i;
12579         float f;
12580         float alpha;
12581         const float *v;
12582         const float *n;
12583         float *c;
12584         vec3_t ambientcolor;
12585         vec3_t diffusecolor;
12586         vec3_t lightdir;
12587         // TODO: optimize
12588         // model lighting
12589         VectorCopy(rsurface.modellight_lightdir, lightdir);
12590         f = 0.5f * r_refdef.lightmapintensity;
12591         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12592         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12593         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12594         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12595         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12596         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12597         alpha = *a;
12598         if (VectorLength2(diffusecolor) > 0)
12599         {
12600                 // q3-style directional shading
12601                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12602                 rsurface.passcolor4f_vertexbuffer = 0;
12603                 rsurface.passcolor4f_bufferoffset = 0;
12604                 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)
12605                 {
12606                         if ((f = DotProduct(n, lightdir)) > 0)
12607                                 VectorMA(ambientcolor, f, diffusecolor, c);
12608                         else
12609                                 VectorCopy(ambientcolor, c);
12610                         c[3] = alpha;
12611                 }
12612                 *r = 1;
12613                 *g = 1;
12614                 *b = 1;
12615                 *a = 1;
12616                 *applycolor = false;
12617         }
12618         else
12619         {
12620                 *r = ambientcolor[0];
12621                 *g = ambientcolor[1];
12622                 *b = ambientcolor[2];
12623                 rsurface.passcolor4f = NULL;
12624                 rsurface.passcolor4f_vertexbuffer = 0;
12625                 rsurface.passcolor4f_bufferoffset = 0;
12626         }
12627 }
12628
12629 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12630 {
12631         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12632         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12633         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12634         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12635         GL_Color(r, g, b, a);
12636         RSurf_DrawBatch();
12637 }
12638
12639 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12640 {
12641         int i;
12642         float f;
12643         const float *v;
12644         float *c;
12645         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12646         {
12647                 f = 1 - RSurf_FogVertex(v);
12648                 c[0] = r;
12649                 c[1] = g;
12650                 c[2] = b;
12651                 c[3] = f * a;
12652         }
12653 }
12654
12655 void RSurf_SetupDepthAndCulling(void)
12656 {
12657         // submodels are biased to avoid z-fighting with world surfaces that they
12658         // may be exactly overlapping (avoids z-fighting artifacts on certain
12659         // doors and things in Quake maps)
12660         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12661         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12662         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12663         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12664 }
12665
12666 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12667 {
12668         // transparent sky would be ridiculous
12669         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12670                 return;
12671         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12672         skyrenderlater = true;
12673         RSurf_SetupDepthAndCulling();
12674         GL_DepthMask(true);
12675         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12676         // skymasking on them, and Quake3 never did sky masking (unlike
12677         // software Quake and software Quake2), so disable the sky masking
12678         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12679         // and skymasking also looks very bad when noclipping outside the
12680         // level, so don't use it then either.
12681         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12682         {
12683                 R_Mesh_ResetTextureState();
12684                 if (skyrendermasked)
12685                 {
12686                         R_SetupShader_DepthOrShadow();
12687                         // depth-only (masking)
12688                         GL_ColorMask(0,0,0,0);
12689                         // just to make sure that braindead drivers don't draw
12690                         // anything despite that colormask...
12691                         GL_BlendFunc(GL_ZERO, GL_ONE);
12692                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12693                         if (rsurface.batchvertex3fbuffer)
12694                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12695                         else
12696                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12697                 }
12698                 else
12699                 {
12700                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12701                         // fog sky
12702                         GL_BlendFunc(GL_ONE, GL_ZERO);
12703                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12704                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12705                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12706                 }
12707                 RSurf_DrawBatch();
12708                 if (skyrendermasked)
12709                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12710         }
12711         R_Mesh_ResetTextureState();
12712         GL_Color(1, 1, 1, 1);
12713 }
12714
12715 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12716 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12717 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12718 {
12719         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12720                 return;
12721         if (prepass)
12722         {
12723                 // render screenspace normalmap to texture
12724                 GL_DepthMask(true);
12725                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12726                 RSurf_DrawBatch();
12727                 return;
12728         }
12729
12730         // bind lightmap texture
12731
12732         // water/refraction/reflection/camera surfaces have to be handled specially
12733         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12734         {
12735                 int start, end, startplaneindex;
12736                 for (start = 0;start < texturenumsurfaces;start = end)
12737                 {
12738                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12739                         if(startplaneindex < 0)
12740                         {
12741                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12742                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12743                                 end = start + 1;
12744                                 continue;
12745                         }
12746                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12747                                 ;
12748                         // now that we have a batch using the same planeindex, render it
12749                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12750                         {
12751                                 // render water or distortion background
12752                                 GL_DepthMask(true);
12753                                 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));
12754                                 RSurf_DrawBatch();
12755                                 // blend surface on top
12756                                 GL_DepthMask(false);
12757                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12758                                 RSurf_DrawBatch();
12759                         }
12760                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12761                         {
12762                                 // render surface with reflection texture as input
12763                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12764                                 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));
12765                                 RSurf_DrawBatch();
12766                         }
12767                 }
12768                 return;
12769         }
12770
12771         // render surface batch normally
12772         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12773         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12774         RSurf_DrawBatch();
12775 }
12776
12777 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12778 {
12779         // OpenGL 1.3 path - anything not completely ancient
12780         qboolean applycolor;
12781         qboolean applyfog;
12782         int layerindex;
12783         const texturelayer_t *layer;
12784         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);
12785         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12786
12787         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12788         {
12789                 vec4_t layercolor;
12790                 int layertexrgbscale;
12791                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12792                 {
12793                         if (layerindex == 0)
12794                                 GL_AlphaTest(true);
12795                         else
12796                         {
12797                                 GL_AlphaTest(false);
12798                                 GL_DepthFunc(GL_EQUAL);
12799                         }
12800                 }
12801                 GL_DepthMask(layer->depthmask && writedepth);
12802                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12803                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12804                 {
12805                         layertexrgbscale = 4;
12806                         VectorScale(layer->color, 0.25f, layercolor);
12807                 }
12808                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12809                 {
12810                         layertexrgbscale = 2;
12811                         VectorScale(layer->color, 0.5f, layercolor);
12812                 }
12813                 else
12814                 {
12815                         layertexrgbscale = 1;
12816                         VectorScale(layer->color, 1.0f, layercolor);
12817                 }
12818                 layercolor[3] = layer->color[3];
12819                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12820                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12821                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12822                 switch (layer->type)
12823                 {
12824                 case TEXTURELAYERTYPE_LITTEXTURE:
12825                         // single-pass lightmapped texture with 2x rgbscale
12826                         R_Mesh_TexBind(0, r_texture_white);
12827                         R_Mesh_TexMatrix(0, NULL);
12828                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12829                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12830                         R_Mesh_TexBind(1, layer->texture);
12831                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12832                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12833                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12834                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12835                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12836                         else if (FAKELIGHT_ENABLED)
12837                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12838                         else if (rsurface.uselightmaptexture)
12839                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12840                         else
12841                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12842                         break;
12843                 case TEXTURELAYERTYPE_TEXTURE:
12844                         // singletexture unlit texture with transparency support
12845                         R_Mesh_TexBind(0, layer->texture);
12846                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12847                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12848                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12849                         R_Mesh_TexBind(1, 0);
12850                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12851                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12852                         break;
12853                 case TEXTURELAYERTYPE_FOG:
12854                         // singletexture fogging
12855                         if (layer->texture)
12856                         {
12857                                 R_Mesh_TexBind(0, layer->texture);
12858                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12859                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12860                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12861                         }
12862                         else
12863                         {
12864                                 R_Mesh_TexBind(0, 0);
12865                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12866                         }
12867                         R_Mesh_TexBind(1, 0);
12868                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12869                         // generate a color array for the fog pass
12870                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12871                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12872                         RSurf_DrawBatch();
12873                         break;
12874                 default:
12875                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12876                 }
12877         }
12878         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12879         {
12880                 GL_DepthFunc(GL_LEQUAL);
12881                 GL_AlphaTest(false);
12882         }
12883 }
12884
12885 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12886 {
12887         // OpenGL 1.1 - crusty old voodoo path
12888         qboolean applyfog;
12889         int layerindex;
12890         const texturelayer_t *layer;
12891         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);
12892         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12893
12894         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12895         {
12896                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12897                 {
12898                         if (layerindex == 0)
12899                                 GL_AlphaTest(true);
12900                         else
12901                         {
12902                                 GL_AlphaTest(false);
12903                                 GL_DepthFunc(GL_EQUAL);
12904                         }
12905                 }
12906                 GL_DepthMask(layer->depthmask && writedepth);
12907                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12908                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12909                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12910                 switch (layer->type)
12911                 {
12912                 case TEXTURELAYERTYPE_LITTEXTURE:
12913                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12914                         {
12915                                 // two-pass lit texture with 2x rgbscale
12916                                 // first the lightmap pass
12917                                 R_Mesh_TexBind(0, r_texture_white);
12918                                 R_Mesh_TexMatrix(0, NULL);
12919                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12920                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12921                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12922                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12923                                 else if (FAKELIGHT_ENABLED)
12924                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12925                                 else if (rsurface.uselightmaptexture)
12926                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12927                                 else
12928                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12929                                 // then apply the texture to it
12930                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12931                                 R_Mesh_TexBind(0, layer->texture);
12932                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12933                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12934                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12935                                 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);
12936                         }
12937                         else
12938                         {
12939                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12940                                 R_Mesh_TexBind(0, layer->texture);
12941                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12942                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12943                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12944                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12945                                         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);
12946                                 else
12947                                         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);
12948                         }
12949                         break;
12950                 case TEXTURELAYERTYPE_TEXTURE:
12951                         // singletexture unlit texture with transparency support
12952                         R_Mesh_TexBind(0, layer->texture);
12953                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12954                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12955                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12956                         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);
12957                         break;
12958                 case TEXTURELAYERTYPE_FOG:
12959                         // singletexture fogging
12960                         if (layer->texture)
12961                         {
12962                                 R_Mesh_TexBind(0, layer->texture);
12963                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12964                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12965                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12966                         }
12967                         else
12968                         {
12969                                 R_Mesh_TexBind(0, 0);
12970                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12971                         }
12972                         // generate a color array for the fog pass
12973                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12974                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12975                         RSurf_DrawBatch();
12976                         break;
12977                 default:
12978                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12979                 }
12980         }
12981         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12982         {
12983                 GL_DepthFunc(GL_LEQUAL);
12984                 GL_AlphaTest(false);
12985         }
12986 }
12987
12988 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12989 {
12990         int vi;
12991         int j;
12992         r_vertexgeneric_t *batchvertex;
12993         float c[4];
12994
12995         GL_AlphaTest(false);
12996 //      R_Mesh_ResetTextureState();
12997         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12998
12999         if(rsurface.texture && rsurface.texture->currentskinframe)
13000         {
13001                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
13002                 c[3] *= rsurface.texture->currentalpha;
13003         }
13004         else
13005         {
13006                 c[0] = 1;
13007                 c[1] = 0;
13008                 c[2] = 1;
13009                 c[3] = 1;
13010         }
13011
13012         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
13013         {
13014                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
13015                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
13016                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
13017         }
13018
13019         // brighten it up (as texture value 127 means "unlit")
13020         c[0] *= 2 * r_refdef.view.colorscale;
13021         c[1] *= 2 * r_refdef.view.colorscale;
13022         c[2] *= 2 * r_refdef.view.colorscale;
13023
13024         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
13025                 c[3] *= r_wateralpha.value;
13026
13027         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
13028         {
13029                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13030                 GL_DepthMask(false);
13031         }
13032         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
13033         {
13034                 GL_BlendFunc(GL_ONE, GL_ONE);
13035                 GL_DepthMask(false);
13036         }
13037         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13038         {
13039                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
13040                 GL_DepthMask(false);
13041         }
13042         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
13043         {
13044                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
13045                 GL_DepthMask(false);
13046         }
13047         else
13048         {
13049                 GL_BlendFunc(GL_ONE, GL_ZERO);
13050                 GL_DepthMask(writedepth);
13051         }
13052
13053         if (r_showsurfaces.integer == 3)
13054         {
13055                 rsurface.passcolor4f = NULL;
13056
13057                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
13058                 {
13059                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13060
13061                         rsurface.passcolor4f = NULL;
13062                         rsurface.passcolor4f_vertexbuffer = 0;
13063                         rsurface.passcolor4f_bufferoffset = 0;
13064                 }
13065                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13066                 {
13067                         qboolean applycolor = true;
13068                         float one = 1.0;
13069
13070                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13071
13072                         r_refdef.lightmapintensity = 1;
13073                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
13074                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13075                 }
13076                 else if (FAKELIGHT_ENABLED)
13077                 {
13078                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13079
13080                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
13081                         RSurf_DrawBatch_GL11_ApplyFakeLight();
13082                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13083                 }
13084                 else
13085                 {
13086                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13087
13088                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13089                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13090                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13091                 }
13092
13093                 if(!rsurface.passcolor4f)
13094                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13095
13096                 RSurf_DrawBatch_GL11_ApplyAmbient();
13097                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13098                 if(r_refdef.fogenabled)
13099                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13100                 RSurf_DrawBatch_GL11_ClampColor();
13101
13102                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13103                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13104                 RSurf_DrawBatch();
13105         }
13106         else if (!r_refdef.view.showdebug)
13107         {
13108                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13109                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13110                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13111                 {
13112                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13113                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13114                 }
13115                 R_Mesh_PrepareVertices_Generic_Unlock();
13116                 RSurf_DrawBatch();
13117         }
13118         else if (r_showsurfaces.integer == 4)
13119         {
13120                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13121                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13122                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13123                 {
13124                         unsigned char c = vi << 3;
13125                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13126                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13127                 }
13128                 R_Mesh_PrepareVertices_Generic_Unlock();
13129                 RSurf_DrawBatch();
13130         }
13131         else if (r_showsurfaces.integer == 2)
13132         {
13133                 const int *e;
13134                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13135                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13136                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13137                 {
13138                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13139                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13140                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13141                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13142                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13143                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13144                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13145                 }
13146                 R_Mesh_PrepareVertices_Generic_Unlock();
13147                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13148         }
13149         else
13150         {
13151                 int texturesurfaceindex;
13152                 int k;
13153                 const msurface_t *surface;
13154                 unsigned char surfacecolor4ub[4];
13155                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13156                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13157                 vi = 0;
13158                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13159                 {
13160                         surface = texturesurfacelist[texturesurfaceindex];
13161                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13162                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13163                         for (j = 0;j < surface->num_vertices;j++)
13164                         {
13165                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13166                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13167                                 vi++;
13168                         }
13169                 }
13170                 R_Mesh_PrepareVertices_Generic_Unlock();
13171                 RSurf_DrawBatch();
13172         }
13173 }
13174
13175 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13176 {
13177         CHECKGLERROR
13178         RSurf_SetupDepthAndCulling();
13179         if (r_showsurfaces.integer)
13180         {
13181                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13182                 return;
13183         }
13184         switch (vid.renderpath)
13185         {
13186         case RENDERPATH_GL20:
13187         case RENDERPATH_CGGL:
13188         case RENDERPATH_D3D9:
13189         case RENDERPATH_D3D10:
13190         case RENDERPATH_D3D11:
13191         case RENDERPATH_SOFT:
13192                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13193                 break;
13194         case RENDERPATH_GL13:
13195                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13196                 break;
13197         case RENDERPATH_GL11:
13198                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13199                 break;
13200         }
13201         CHECKGLERROR
13202 }
13203
13204 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13205 {
13206         CHECKGLERROR
13207         RSurf_SetupDepthAndCulling();
13208         if (r_showsurfaces.integer)
13209         {
13210                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13211                 return;
13212         }
13213         switch (vid.renderpath)
13214         {
13215         case RENDERPATH_GL20:
13216         case RENDERPATH_CGGL:
13217         case RENDERPATH_D3D9:
13218         case RENDERPATH_D3D10:
13219         case RENDERPATH_D3D11:
13220         case RENDERPATH_SOFT:
13221                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13222                 break;
13223         case RENDERPATH_GL13:
13224                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13225                 break;
13226         case RENDERPATH_GL11:
13227                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13228                 break;
13229         }
13230         CHECKGLERROR
13231 }
13232
13233 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13234 {
13235         int i, j;
13236         int texturenumsurfaces, endsurface;
13237         texture_t *texture;
13238         const msurface_t *surface;
13239 #define MAXBATCH_TRANSPARENTSURFACES 256
13240         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13241
13242         // if the model is static it doesn't matter what value we give for
13243         // wantnormals and wanttangents, so this logic uses only rules applicable
13244         // to a model, knowing that they are meaningless otherwise
13245         if (ent == r_refdef.scene.worldentity)
13246                 RSurf_ActiveWorldEntity();
13247         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13248                 RSurf_ActiveModelEntity(ent, false, false, false);
13249         else
13250         {
13251                 switch (vid.renderpath)
13252                 {
13253                 case RENDERPATH_GL20:
13254                 case RENDERPATH_CGGL:
13255                 case RENDERPATH_D3D9:
13256                 case RENDERPATH_D3D10:
13257                 case RENDERPATH_D3D11:
13258                 case RENDERPATH_SOFT:
13259                         RSurf_ActiveModelEntity(ent, true, true, false);
13260                         break;
13261                 case RENDERPATH_GL13:
13262                 case RENDERPATH_GL11:
13263                         RSurf_ActiveModelEntity(ent, true, false, false);
13264                         break;
13265                 }
13266         }
13267
13268         if (r_transparentdepthmasking.integer)
13269         {
13270                 qboolean setup = false;
13271                 for (i = 0;i < numsurfaces;i = j)
13272                 {
13273                         j = i + 1;
13274                         surface = rsurface.modelsurfaces + surfacelist[i];
13275                         texture = surface->texture;
13276                         rsurface.texture = R_GetCurrentTexture(texture);
13277                         rsurface.lightmaptexture = NULL;
13278                         rsurface.deluxemaptexture = NULL;
13279                         rsurface.uselightmaptexture = false;
13280                         // scan ahead until we find a different texture
13281                         endsurface = min(i + 1024, numsurfaces);
13282                         texturenumsurfaces = 0;
13283                         texturesurfacelist[texturenumsurfaces++] = surface;
13284                         for (;j < endsurface;j++)
13285                         {
13286                                 surface = rsurface.modelsurfaces + surfacelist[j];
13287                                 if (texture != surface->texture)
13288                                         break;
13289                                 texturesurfacelist[texturenumsurfaces++] = surface;
13290                         }
13291                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13292                                 continue;
13293                         // render the range of surfaces as depth
13294                         if (!setup)
13295                         {
13296                                 setup = true;
13297                                 GL_ColorMask(0,0,0,0);
13298                                 GL_Color(1,1,1,1);
13299                                 GL_DepthTest(true);
13300                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13301                                 GL_DepthMask(true);
13302                                 GL_AlphaTest(false);
13303 //                              R_Mesh_ResetTextureState();
13304                                 R_SetupShader_DepthOrShadow();
13305                         }
13306                         RSurf_SetupDepthAndCulling();
13307                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13308                         if (rsurface.batchvertex3fbuffer)
13309                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13310                         else
13311                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13312                         RSurf_DrawBatch();
13313                 }
13314                 if (setup)
13315                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13316         }
13317
13318         for (i = 0;i < numsurfaces;i = j)
13319         {
13320                 j = i + 1;
13321                 surface = rsurface.modelsurfaces + surfacelist[i];
13322                 texture = surface->texture;
13323                 rsurface.texture = R_GetCurrentTexture(texture);
13324                 // scan ahead until we find a different texture
13325                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13326                 texturenumsurfaces = 0;
13327                 texturesurfacelist[texturenumsurfaces++] = surface;
13328                 if(FAKELIGHT_ENABLED)
13329                 {
13330                         rsurface.lightmaptexture = NULL;
13331                         rsurface.deluxemaptexture = NULL;
13332                         rsurface.uselightmaptexture = false;
13333                         for (;j < endsurface;j++)
13334                         {
13335                                 surface = rsurface.modelsurfaces + surfacelist[j];
13336                                 if (texture != surface->texture)
13337                                         break;
13338                                 texturesurfacelist[texturenumsurfaces++] = surface;
13339                         }
13340                 }
13341                 else
13342                 {
13343                         rsurface.lightmaptexture = surface->lightmaptexture;
13344                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13345                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13346                         for (;j < endsurface;j++)
13347                         {
13348                                 surface = rsurface.modelsurfaces + surfacelist[j];
13349                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13350                                         break;
13351                                 texturesurfacelist[texturenumsurfaces++] = surface;
13352                         }
13353                 }
13354                 // render the range of surfaces
13355                 if (ent == r_refdef.scene.worldentity)
13356                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13357                 else
13358                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13359         }
13360         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13361         GL_AlphaTest(false);
13362 }
13363
13364 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13365 {
13366         // transparent surfaces get pushed off into the transparent queue
13367         int surfacelistindex;
13368         const msurface_t *surface;
13369         vec3_t tempcenter, center;
13370         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13371         {
13372                 surface = texturesurfacelist[surfacelistindex];
13373                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13374                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13375                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13376                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13377                 if (queueentity->transparent_offset) // transparent offset
13378                 {
13379                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13380                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13381                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13382                 }
13383                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13384         }
13385 }
13386
13387 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13388 {
13389         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13390                 return;
13391         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13392                 return;
13393         RSurf_SetupDepthAndCulling();
13394         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13395         if (rsurface.batchvertex3fbuffer)
13396                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13397         else
13398                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13399         RSurf_DrawBatch();
13400 }
13401
13402 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13403 {
13404         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13405         CHECKGLERROR
13406         if (depthonly)
13407                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13408         else if (prepass)
13409         {
13410                 if (!rsurface.texture->currentnumlayers)
13411                         return;
13412                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13413                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13414                 else
13415                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13416         }
13417         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13418                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13419         else if (!rsurface.texture->currentnumlayers)
13420                 return;
13421         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13422         {
13423                 // in the deferred case, transparent surfaces were queued during prepass
13424                 if (!r_shadow_usingdeferredprepass)
13425                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13426         }
13427         else
13428         {
13429                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13430                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13431         }
13432         CHECKGLERROR
13433 }
13434
13435 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13436 {
13437         int i, j;
13438         texture_t *texture;
13439         R_FrameData_SetMark();
13440         // break the surface list down into batches by texture and use of lightmapping
13441         for (i = 0;i < numsurfaces;i = j)
13442         {
13443                 j = i + 1;
13444                 // texture is the base texture pointer, rsurface.texture is the
13445                 // current frame/skin the texture is directing us to use (for example
13446                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13447                 // use skin 1 instead)
13448                 texture = surfacelist[i]->texture;
13449                 rsurface.texture = R_GetCurrentTexture(texture);
13450                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13451                 {
13452                         // if this texture is not the kind we want, skip ahead to the next one
13453                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13454                                 ;
13455                         continue;
13456                 }
13457                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13458                 {
13459                         rsurface.lightmaptexture = NULL;
13460                         rsurface.deluxemaptexture = NULL;
13461                         rsurface.uselightmaptexture = false;
13462                         // simply scan ahead until we find a different texture or lightmap state
13463                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13464                                 ;
13465                 }
13466                 else
13467                 {
13468                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13469                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13470                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13471                         // simply scan ahead until we find a different texture or lightmap state
13472                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13473                                 ;
13474                 }
13475                 // render the range of surfaces
13476                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13477         }
13478         R_FrameData_ReturnToMark();
13479 }
13480
13481 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13482 {
13483         CHECKGLERROR
13484         if (depthonly)
13485                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13486         else if (prepass)
13487         {
13488                 if (!rsurface.texture->currentnumlayers)
13489                         return;
13490                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13491                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13492                 else
13493                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13494         }
13495         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13496                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13497         else if (!rsurface.texture->currentnumlayers)
13498                 return;
13499         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13500         {
13501                 // in the deferred case, transparent surfaces were queued during prepass
13502                 if (!r_shadow_usingdeferredprepass)
13503                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13504         }
13505         else
13506         {
13507                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13508                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13509         }
13510         CHECKGLERROR
13511 }
13512
13513 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13514 {
13515         int i, j;
13516         texture_t *texture;
13517         R_FrameData_SetMark();
13518         // break the surface list down into batches by texture and use of lightmapping
13519         for (i = 0;i < numsurfaces;i = j)
13520         {
13521                 j = i + 1;
13522                 // texture is the base texture pointer, rsurface.texture is the
13523                 // current frame/skin the texture is directing us to use (for example
13524                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13525                 // use skin 1 instead)
13526                 texture = surfacelist[i]->texture;
13527                 rsurface.texture = R_GetCurrentTexture(texture);
13528                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13529                 {
13530                         // if this texture is not the kind we want, skip ahead to the next one
13531                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13532                                 ;
13533                         continue;
13534                 }
13535                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13536                 {
13537                         rsurface.lightmaptexture = NULL;
13538                         rsurface.deluxemaptexture = NULL;
13539                         rsurface.uselightmaptexture = false;
13540                         // simply scan ahead until we find a different texture or lightmap state
13541                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13542                                 ;
13543                 }
13544                 else
13545                 {
13546                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13547                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13548                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13549                         // simply scan ahead until we find a different texture or lightmap state
13550                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13551                                 ;
13552                 }
13553                 // render the range of surfaces
13554                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13555         }
13556         R_FrameData_ReturnToMark();
13557 }
13558
13559 float locboxvertex3f[6*4*3] =
13560 {
13561         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13562         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13563         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13564         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13565         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13566         1,0,0, 0,0,0, 0,1,0, 1,1,0
13567 };
13568
13569 unsigned short locboxelements[6*2*3] =
13570 {
13571          0, 1, 2, 0, 2, 3,
13572          4, 5, 6, 4, 6, 7,
13573          8, 9,10, 8,10,11,
13574         12,13,14, 12,14,15,
13575         16,17,18, 16,18,19,
13576         20,21,22, 20,22,23
13577 };
13578
13579 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13580 {
13581         int i, j;
13582         cl_locnode_t *loc = (cl_locnode_t *)ent;
13583         vec3_t mins, size;
13584         float vertex3f[6*4*3];
13585         CHECKGLERROR
13586         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13587         GL_DepthMask(false);
13588         GL_DepthRange(0, 1);
13589         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13590         GL_DepthTest(true);
13591         GL_CullFace(GL_NONE);
13592         R_EntityMatrix(&identitymatrix);
13593
13594 //      R_Mesh_ResetTextureState();
13595
13596         i = surfacelist[0];
13597         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13598                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13599                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13600                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13601
13602         if (VectorCompare(loc->mins, loc->maxs))
13603         {
13604                 VectorSet(size, 2, 2, 2);
13605                 VectorMA(loc->mins, -0.5f, size, mins);
13606         }
13607         else
13608         {
13609                 VectorCopy(loc->mins, mins);
13610                 VectorSubtract(loc->maxs, loc->mins, size);
13611         }
13612
13613         for (i = 0;i < 6*4*3;)
13614                 for (j = 0;j < 3;j++, i++)
13615                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13616
13617         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13618         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13619         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13620 }
13621
13622 void R_DrawLocs(void)
13623 {
13624         int index;
13625         cl_locnode_t *loc, *nearestloc;
13626         vec3_t center;
13627         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13628         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13629         {
13630                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13631                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13632         }
13633 }
13634
13635 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13636 {
13637         if (decalsystem->decals)
13638                 Mem_Free(decalsystem->decals);
13639         memset(decalsystem, 0, sizeof(*decalsystem));
13640 }
13641
13642 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)
13643 {
13644         tridecal_t *decal;
13645         tridecal_t *decals;
13646         int i;
13647
13648         // expand or initialize the system
13649         if (decalsystem->maxdecals <= decalsystem->numdecals)
13650         {
13651                 decalsystem_t old = *decalsystem;
13652                 qboolean useshortelements;
13653                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13654                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13655                 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)));
13656                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13657                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13658                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13659                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13660                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13661                 if (decalsystem->numdecals)
13662                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13663                 if (old.decals)
13664                         Mem_Free(old.decals);
13665                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13666                         decalsystem->element3i[i] = i;
13667                 if (useshortelements)
13668                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13669                                 decalsystem->element3s[i] = i;
13670         }
13671
13672         // grab a decal and search for another free slot for the next one
13673         decals = decalsystem->decals;
13674         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13675         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13676                 ;
13677         decalsystem->freedecal = i;
13678         if (decalsystem->numdecals <= i)
13679                 decalsystem->numdecals = i + 1;
13680
13681         // initialize the decal
13682         decal->lived = 0;
13683         decal->triangleindex = triangleindex;
13684         decal->surfaceindex = surfaceindex;
13685         decal->decalsequence = decalsequence;
13686         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13687         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13688         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13689         decal->color4ub[0][3] = 255;
13690         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13691         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13692         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13693         decal->color4ub[1][3] = 255;
13694         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13695         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13696         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13697         decal->color4ub[2][3] = 255;
13698         decal->vertex3f[0][0] = v0[0];
13699         decal->vertex3f[0][1] = v0[1];
13700         decal->vertex3f[0][2] = v0[2];
13701         decal->vertex3f[1][0] = v1[0];
13702         decal->vertex3f[1][1] = v1[1];
13703         decal->vertex3f[1][2] = v1[2];
13704         decal->vertex3f[2][0] = v2[0];
13705         decal->vertex3f[2][1] = v2[1];
13706         decal->vertex3f[2][2] = v2[2];
13707         decal->texcoord2f[0][0] = t0[0];
13708         decal->texcoord2f[0][1] = t0[1];
13709         decal->texcoord2f[1][0] = t1[0];
13710         decal->texcoord2f[1][1] = t1[1];
13711         decal->texcoord2f[2][0] = t2[0];
13712         decal->texcoord2f[2][1] = t2[1];
13713 }
13714
13715 extern cvar_t cl_decals_bias;
13716 extern cvar_t cl_decals_models;
13717 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13718 // baseparms, parms, temps
13719 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)
13720 {
13721         int cornerindex;
13722         int index;
13723         float v[9][3];
13724         const float *vertex3f;
13725         int numpoints;
13726         float points[2][9][3];
13727         float temp[3];
13728         float tc[9][2];
13729         float f;
13730         float c[9][4];
13731         const int *e;
13732
13733         e = rsurface.modelelement3i + 3*triangleindex;
13734
13735         vertex3f = rsurface.modelvertex3f;
13736
13737         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13738         {
13739                 index = 3*e[cornerindex];
13740                 VectorCopy(vertex3f + index, v[cornerindex]);
13741         }
13742         // cull backfaces
13743         //TriangleNormal(v[0], v[1], v[2], normal);
13744         //if (DotProduct(normal, localnormal) < 0.0f)
13745         //      continue;
13746         // clip by each of the box planes formed from the projection matrix
13747         // if anything survives, we emit the decal
13748         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]);
13749         if (numpoints < 3)
13750                 return;
13751         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]);
13752         if (numpoints < 3)
13753                 return;
13754         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]);
13755         if (numpoints < 3)
13756                 return;
13757         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]);
13758         if (numpoints < 3)
13759                 return;
13760         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]);
13761         if (numpoints < 3)
13762                 return;
13763         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]);
13764         if (numpoints < 3)
13765                 return;
13766         // some part of the triangle survived, so we have to accept it...
13767         if (dynamic)
13768         {
13769                 // dynamic always uses the original triangle
13770                 numpoints = 3;
13771                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13772                 {
13773                         index = 3*e[cornerindex];
13774                         VectorCopy(vertex3f + index, v[cornerindex]);
13775                 }
13776         }
13777         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13778         {
13779                 // convert vertex positions to texcoords
13780                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13781                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13782                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13783                 // calculate distance fade from the projection origin
13784                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13785                 f = bound(0.0f, f, 1.0f);
13786                 c[cornerindex][0] = r * f;
13787                 c[cornerindex][1] = g * f;
13788                 c[cornerindex][2] = b * f;
13789                 c[cornerindex][3] = 1.0f;
13790                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13791         }
13792         if (dynamic)
13793                 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);
13794         else
13795                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13796                         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);
13797 }
13798 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)
13799 {
13800         matrix4x4_t projection;
13801         decalsystem_t *decalsystem;
13802         qboolean dynamic;
13803         dp_model_t *model;
13804         const msurface_t *surface;
13805         const msurface_t *surfaces;
13806         const int *surfacelist;
13807         const texture_t *texture;
13808         int numtriangles;
13809         int numsurfacelist;
13810         int surfacelistindex;
13811         int surfaceindex;
13812         int triangleindex;
13813         float localorigin[3];
13814         float localnormal[3];
13815         float localmins[3];
13816         float localmaxs[3];
13817         float localsize;
13818         //float normal[3];
13819         float planes[6][4];
13820         float angles[3];
13821         bih_t *bih;
13822         int bih_triangles_count;
13823         int bih_triangles[256];
13824         int bih_surfaces[256];
13825
13826         decalsystem = &ent->decalsystem;
13827         model = ent->model;
13828         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13829         {
13830                 R_DecalSystem_Reset(&ent->decalsystem);
13831                 return;
13832         }
13833
13834         if (!model->brush.data_leafs && !cl_decals_models.integer)
13835         {
13836                 if (decalsystem->model)
13837                         R_DecalSystem_Reset(decalsystem);
13838                 return;
13839         }
13840
13841         if (decalsystem->model != model)
13842                 R_DecalSystem_Reset(decalsystem);
13843         decalsystem->model = model;
13844
13845         RSurf_ActiveModelEntity(ent, false, false, false);
13846
13847         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13848         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13849         VectorNormalize(localnormal);
13850         localsize = worldsize*rsurface.inversematrixscale;
13851         localmins[0] = localorigin[0] - localsize;
13852         localmins[1] = localorigin[1] - localsize;
13853         localmins[2] = localorigin[2] - localsize;
13854         localmaxs[0] = localorigin[0] + localsize;
13855         localmaxs[1] = localorigin[1] + localsize;
13856         localmaxs[2] = localorigin[2] + localsize;
13857
13858         //VectorCopy(localnormal, planes[4]);
13859         //VectorVectors(planes[4], planes[2], planes[0]);
13860         AnglesFromVectors(angles, localnormal, NULL, false);
13861         AngleVectors(angles, planes[0], planes[2], planes[4]);
13862         VectorNegate(planes[0], planes[1]);
13863         VectorNegate(planes[2], planes[3]);
13864         VectorNegate(planes[4], planes[5]);
13865         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13866         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13867         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13868         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13869         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13870         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13871
13872 #if 1
13873 // works
13874 {
13875         matrix4x4_t forwardprojection;
13876         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13877         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13878 }
13879 #else
13880 // broken
13881 {
13882         float projectionvector[4][3];
13883         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13884         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13885         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13886         projectionvector[0][0] = planes[0][0] * ilocalsize;
13887         projectionvector[0][1] = planes[1][0] * ilocalsize;
13888         projectionvector[0][2] = planes[2][0] * ilocalsize;
13889         projectionvector[1][0] = planes[0][1] * ilocalsize;
13890         projectionvector[1][1] = planes[1][1] * ilocalsize;
13891         projectionvector[1][2] = planes[2][1] * ilocalsize;
13892         projectionvector[2][0] = planes[0][2] * ilocalsize;
13893         projectionvector[2][1] = planes[1][2] * ilocalsize;
13894         projectionvector[2][2] = planes[2][2] * ilocalsize;
13895         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13896         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13897         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13898         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13899 }
13900 #endif
13901
13902         dynamic = model->surfmesh.isanimated;
13903         numsurfacelist = model->nummodelsurfaces;
13904         surfacelist = model->sortedmodelsurfaces;
13905         surfaces = model->data_surfaces;
13906
13907         bih = NULL;
13908         bih_triangles_count = -1;
13909         if(!dynamic)
13910         {
13911                 if(model->render_bih.numleafs)
13912                         bih = &model->render_bih;
13913                 else if(model->collision_bih.numleafs)
13914                         bih = &model->collision_bih;
13915         }
13916         if(bih)
13917                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13918         if(bih_triangles_count == 0)
13919                 return;
13920         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13921                 return;
13922         if(bih_triangles_count > 0)
13923         {
13924                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13925                 {
13926                         surfaceindex = bih_surfaces[triangleindex];
13927                         surface = surfaces + surfaceindex;
13928                         texture = surface->texture;
13929                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13930                                 continue;
13931                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13932                                 continue;
13933                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13934                 }
13935         }
13936         else
13937         {
13938                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13939                 {
13940                         surfaceindex = surfacelist[surfacelistindex];
13941                         surface = surfaces + surfaceindex;
13942                         // check cull box first because it rejects more than any other check
13943                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13944                                 continue;
13945                         // skip transparent surfaces
13946                         texture = surface->texture;
13947                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13948                                 continue;
13949                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13950                                 continue;
13951                         numtriangles = surface->num_triangles;
13952                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13953                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13954                 }
13955         }
13956 }
13957
13958 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13959 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)
13960 {
13961         int renderentityindex;
13962         float worldmins[3];
13963         float worldmaxs[3];
13964         entity_render_t *ent;
13965
13966         if (!cl_decals_newsystem.integer)
13967                 return;
13968
13969         worldmins[0] = worldorigin[0] - worldsize;
13970         worldmins[1] = worldorigin[1] - worldsize;
13971         worldmins[2] = worldorigin[2] - worldsize;
13972         worldmaxs[0] = worldorigin[0] + worldsize;
13973         worldmaxs[1] = worldorigin[1] + worldsize;
13974         worldmaxs[2] = worldorigin[2] + worldsize;
13975
13976         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13977
13978         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13979         {
13980                 ent = r_refdef.scene.entities[renderentityindex];
13981                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13982                         continue;
13983
13984                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13985         }
13986 }
13987
13988 typedef struct r_decalsystem_splatqueue_s
13989 {
13990         vec3_t worldorigin;
13991         vec3_t worldnormal;
13992         float color[4];
13993         float tcrange[4];
13994         float worldsize;
13995         int decalsequence;
13996 }
13997 r_decalsystem_splatqueue_t;
13998
13999 int r_decalsystem_numqueued = 0;
14000 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
14001
14002 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)
14003 {
14004         r_decalsystem_splatqueue_t *queue;
14005
14006         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
14007                 return;
14008
14009         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
14010         VectorCopy(worldorigin, queue->worldorigin);
14011         VectorCopy(worldnormal, queue->worldnormal);
14012         Vector4Set(queue->color, r, g, b, a);
14013         Vector4Set(queue->tcrange, s1, t1, s2, t2);
14014         queue->worldsize = worldsize;
14015         queue->decalsequence = cl.decalsequence++;
14016 }
14017
14018 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
14019 {
14020         int i;
14021         r_decalsystem_splatqueue_t *queue;
14022
14023         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
14024                 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);
14025         r_decalsystem_numqueued = 0;
14026 }
14027
14028 extern cvar_t cl_decals_max;
14029 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
14030 {
14031         int i;
14032         decalsystem_t *decalsystem = &ent->decalsystem;
14033         int numdecals;
14034         int killsequence;
14035         tridecal_t *decal;
14036         float frametime;
14037         float lifetime;
14038
14039         if (!decalsystem->numdecals)
14040                 return;
14041
14042         if (r_showsurfaces.integer)
14043                 return;
14044
14045         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14046         {
14047                 R_DecalSystem_Reset(decalsystem);
14048                 return;
14049         }
14050
14051         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
14052         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
14053
14054         if (decalsystem->lastupdatetime)
14055                 frametime = (cl.time - decalsystem->lastupdatetime);
14056         else
14057                 frametime = 0;
14058         decalsystem->lastupdatetime = cl.time;
14059         decal = decalsystem->decals;
14060         numdecals = decalsystem->numdecals;
14061
14062         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14063         {
14064                 if (decal->color4ub[0][3])
14065                 {
14066                         decal->lived += frametime;
14067                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
14068                         {
14069                                 memset(decal, 0, sizeof(*decal));
14070                                 if (decalsystem->freedecal > i)
14071                                         decalsystem->freedecal = i;
14072                         }
14073                 }
14074         }
14075         decal = decalsystem->decals;
14076         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
14077                 numdecals--;
14078
14079         // collapse the array by shuffling the tail decals into the gaps
14080         for (;;)
14081         {
14082                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
14083                         decalsystem->freedecal++;
14084                 if (decalsystem->freedecal == numdecals)
14085                         break;
14086                 decal[decalsystem->freedecal] = decal[--numdecals];
14087         }
14088
14089         decalsystem->numdecals = numdecals;
14090
14091         if (numdecals <= 0)
14092         {
14093                 // if there are no decals left, reset decalsystem
14094                 R_DecalSystem_Reset(decalsystem);
14095         }
14096 }
14097
14098 extern skinframe_t *decalskinframe;
14099 static void R_DrawModelDecals_Entity(entity_render_t *ent)
14100 {
14101         int i;
14102         decalsystem_t *decalsystem = &ent->decalsystem;
14103         int numdecals;
14104         tridecal_t *decal;
14105         float faderate;
14106         float alpha;
14107         float *v3f;
14108         float *c4f;
14109         float *t2f;
14110         const int *e;
14111         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14112         int numtris = 0;
14113
14114         numdecals = decalsystem->numdecals;
14115         if (!numdecals)
14116                 return;
14117
14118         if (r_showsurfaces.integer)
14119                 return;
14120
14121         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14122         {
14123                 R_DecalSystem_Reset(decalsystem);
14124                 return;
14125         }
14126
14127         // if the model is static it doesn't matter what value we give for
14128         // wantnormals and wanttangents, so this logic uses only rules applicable
14129         // to a model, knowing that they are meaningless otherwise
14130         if (ent == r_refdef.scene.worldentity)
14131                 RSurf_ActiveWorldEntity();
14132         else
14133                 RSurf_ActiveModelEntity(ent, false, false, false);
14134
14135         decalsystem->lastupdatetime = cl.time;
14136         decal = decalsystem->decals;
14137
14138         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14139
14140         // update vertex positions for animated models
14141         v3f = decalsystem->vertex3f;
14142         c4f = decalsystem->color4f;
14143         t2f = decalsystem->texcoord2f;
14144         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14145         {
14146                 if (!decal->color4ub[0][3])
14147                         continue;
14148
14149                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14150                         continue;
14151
14152                 // update color values for fading decals
14153                 if (decal->lived >= cl_decals_time.value)
14154                 {
14155                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14156                         alpha *= (1.0f/255.0f);
14157                 }
14158                 else
14159                         alpha = 1.0f/255.0f;
14160
14161                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14162                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14163                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14164                 c4f[ 3] = 1;
14165                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14166                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14167                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14168                 c4f[ 7] = 1;
14169                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14170                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14171                 c4f[10] = decal->color4ub[2][2] * alpha;
14172                 c4f[11] = 1;
14173
14174                 t2f[0] = decal->texcoord2f[0][0];
14175                 t2f[1] = decal->texcoord2f[0][1];
14176                 t2f[2] = decal->texcoord2f[1][0];
14177                 t2f[3] = decal->texcoord2f[1][1];
14178                 t2f[4] = decal->texcoord2f[2][0];
14179                 t2f[5] = decal->texcoord2f[2][1];
14180
14181                 // update vertex positions for animated models
14182                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14183                 {
14184                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14185                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14186                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14187                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14188                 }
14189                 else
14190                 {
14191                         VectorCopy(decal->vertex3f[0], v3f);
14192                         VectorCopy(decal->vertex3f[1], v3f + 3);
14193                         VectorCopy(decal->vertex3f[2], v3f + 6);
14194                 }
14195
14196                 if (r_refdef.fogenabled)
14197                 {
14198                         alpha = RSurf_FogVertex(v3f);
14199                         VectorScale(c4f, alpha, c4f);
14200                         alpha = RSurf_FogVertex(v3f + 3);
14201                         VectorScale(c4f + 4, alpha, c4f + 4);
14202                         alpha = RSurf_FogVertex(v3f + 6);
14203                         VectorScale(c4f + 8, alpha, c4f + 8);
14204                 }
14205
14206                 v3f += 9;
14207                 c4f += 12;
14208                 t2f += 6;
14209                 numtris++;
14210         }
14211
14212         if (numtris > 0)
14213         {
14214                 r_refdef.stats.drawndecals += numtris;
14215
14216                 // now render the decals all at once
14217                 // (this assumes they all use one particle font texture!)
14218                 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);
14219 //              R_Mesh_ResetTextureState();
14220                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14221                 GL_DepthMask(false);
14222                 GL_DepthRange(0, 1);
14223                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14224                 GL_DepthTest(true);
14225                 GL_CullFace(GL_NONE);
14226                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14227                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14228                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14229         }
14230 }
14231
14232 static void R_DrawModelDecals(void)
14233 {
14234         int i, numdecals;
14235
14236         // fade faster when there are too many decals
14237         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14238         for (i = 0;i < r_refdef.scene.numentities;i++)
14239                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14240
14241         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14242         for (i = 0;i < r_refdef.scene.numentities;i++)
14243                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14244                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14245
14246         R_DecalSystem_ApplySplatEntitiesQueue();
14247
14248         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14249         for (i = 0;i < r_refdef.scene.numentities;i++)
14250                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14251
14252         r_refdef.stats.totaldecals += numdecals;
14253
14254         if (r_showsurfaces.integer)
14255                 return;
14256
14257         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14258
14259         for (i = 0;i < r_refdef.scene.numentities;i++)
14260         {
14261                 if (!r_refdef.viewcache.entityvisible[i])
14262                         continue;
14263                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14264                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14265         }
14266 }
14267
14268 extern cvar_t mod_collision_bih;
14269 void R_DrawDebugModel(void)
14270 {
14271         entity_render_t *ent = rsurface.entity;
14272         int i, j, k, l, flagsmask;
14273         const msurface_t *surface;
14274         dp_model_t *model = ent->model;
14275         vec3_t v;
14276
14277         switch(vid.renderpath)
14278         {
14279         case RENDERPATH_GL11:
14280         case RENDERPATH_GL13:
14281         case RENDERPATH_GL20:
14282         case RENDERPATH_CGGL:
14283                 break;
14284         case RENDERPATH_D3D9:
14285                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14286                 return;
14287         case RENDERPATH_D3D10:
14288                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14289                 return;
14290         case RENDERPATH_D3D11:
14291                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14292                 return;
14293         case RENDERPATH_SOFT:
14294                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14295                 return;
14296         }
14297
14298         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14299
14300 //      R_Mesh_ResetTextureState();
14301         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14302         GL_DepthRange(0, 1);
14303         GL_DepthTest(!r_showdisabledepthtest.integer);
14304         GL_DepthMask(false);
14305         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14306
14307         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14308         {
14309                 int triangleindex;
14310                 int bihleafindex;
14311                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14312                 const q3mbrush_t *brush;
14313                 const bih_t *bih = &model->collision_bih;
14314                 const bih_leaf_t *bihleaf;
14315                 float vertex3f[3][3];
14316                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14317                 cullbox = false;
14318                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14319                 {
14320                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14321                                 continue;
14322                         switch (bihleaf->type)
14323                         {
14324                         case BIH_BRUSH:
14325                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14326                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14327                                 {
14328                                         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);
14329                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14330                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14331                                 }
14332                                 break;
14333                         case BIH_COLLISIONTRIANGLE:
14334                                 triangleindex = bihleaf->itemindex;
14335                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14336                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14337                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14338                                 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);
14339                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14340                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14341                                 break;
14342                         case BIH_RENDERTRIANGLE:
14343                                 triangleindex = bihleaf->itemindex;
14344                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14345                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14346                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14347                                 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);
14348                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14349                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14350                                 break;
14351                         }
14352                 }
14353         }
14354
14355         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14356
14357         if (r_showtris.integer || (r_shownormals.value != 0))
14358         {
14359                 if (r_showdisabledepthtest.integer)
14360                 {
14361                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14362                         GL_DepthMask(false);
14363                 }
14364                 else
14365                 {
14366                         GL_BlendFunc(GL_ONE, GL_ZERO);
14367                         GL_DepthMask(true);
14368                 }
14369                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14370                 {
14371                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14372                                 continue;
14373                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14374                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14375                         {
14376                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14377                                 if (r_showtris.value > 0)
14378                                 {
14379                                         if (!rsurface.texture->currentlayers->depthmask)
14380                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14381                                         else if (ent == r_refdef.scene.worldentity)
14382                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14383                                         else
14384                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14385                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14386                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14387                                         RSurf_DrawBatch();
14388                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14389                                         CHECKGLERROR
14390                                 }
14391                                 if (r_shownormals.value < 0)
14392                                 {
14393                                         qglBegin(GL_LINES);
14394                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14395                                         {
14396                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14397                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14398                                                 qglVertex3f(v[0], v[1], v[2]);
14399                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14400                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14401                                                 qglVertex3f(v[0], v[1], v[2]);
14402                                         }
14403                                         qglEnd();
14404                                         CHECKGLERROR
14405                                 }
14406                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14407                                 {
14408                                         qglBegin(GL_LINES);
14409                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14410                                         {
14411                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14412                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14413                                                 qglVertex3f(v[0], v[1], v[2]);
14414                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14415                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14416                                                 qglVertex3f(v[0], v[1], v[2]);
14417                                         }
14418                                         qglEnd();
14419                                         CHECKGLERROR
14420                                         qglBegin(GL_LINES);
14421                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14422                                         {
14423                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14424                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14425                                                 qglVertex3f(v[0], v[1], v[2]);
14426                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14427                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14428                                                 qglVertex3f(v[0], v[1], v[2]);
14429                                         }
14430                                         qglEnd();
14431                                         CHECKGLERROR
14432                                         qglBegin(GL_LINES);
14433                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14434                                         {
14435                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14436                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14437                                                 qglVertex3f(v[0], v[1], v[2]);
14438                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14439                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14440                                                 qglVertex3f(v[0], v[1], v[2]);
14441                                         }
14442                                         qglEnd();
14443                                         CHECKGLERROR
14444                                 }
14445                         }
14446                 }
14447                 rsurface.texture = NULL;
14448         }
14449 }
14450
14451 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14452 int r_maxsurfacelist = 0;
14453 const msurface_t **r_surfacelist = NULL;
14454 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14455 {
14456         int i, j, endj, flagsmask;
14457         dp_model_t *model = r_refdef.scene.worldmodel;
14458         msurface_t *surfaces;
14459         unsigned char *update;
14460         int numsurfacelist = 0;
14461         if (model == NULL)
14462                 return;
14463
14464         if (r_maxsurfacelist < model->num_surfaces)
14465         {
14466                 r_maxsurfacelist = model->num_surfaces;
14467                 if (r_surfacelist)
14468                         Mem_Free((msurface_t**)r_surfacelist);
14469                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14470         }
14471
14472         RSurf_ActiveWorldEntity();
14473
14474         surfaces = model->data_surfaces;
14475         update = model->brushq1.lightmapupdateflags;
14476
14477         // update light styles on this submodel
14478         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14479         {
14480                 model_brush_lightstyleinfo_t *style;
14481                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14482                 {
14483                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14484                         {
14485                                 int *list = style->surfacelist;
14486                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14487                                 for (j = 0;j < style->numsurfaces;j++)
14488                                         update[list[j]] = true;
14489                         }
14490                 }
14491         }
14492
14493         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14494
14495         if (debug)
14496         {
14497                 R_DrawDebugModel();
14498                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14499                 return;
14500         }
14501
14502         rsurface.lightmaptexture = NULL;
14503         rsurface.deluxemaptexture = NULL;
14504         rsurface.uselightmaptexture = false;
14505         rsurface.texture = NULL;
14506         rsurface.rtlight = NULL;
14507         numsurfacelist = 0;
14508         // add visible surfaces to draw list
14509         for (i = 0;i < model->nummodelsurfaces;i++)
14510         {
14511                 j = model->sortedmodelsurfaces[i];
14512                 if (r_refdef.viewcache.world_surfacevisible[j])
14513                         r_surfacelist[numsurfacelist++] = surfaces + j;
14514         }
14515         // update lightmaps if needed
14516         if (model->brushq1.firstrender)
14517         {
14518                 model->brushq1.firstrender = false;
14519                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14520                         if (update[j])
14521                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14522         }
14523         else if (update)
14524         {
14525                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14526                         if (r_refdef.viewcache.world_surfacevisible[j])
14527                                 if (update[j])
14528                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14529         }
14530         // don't do anything if there were no surfaces
14531         if (!numsurfacelist)
14532         {
14533                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14534                 return;
14535         }
14536         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14537         GL_AlphaTest(false);
14538
14539         // add to stats if desired
14540         if (r_speeds.integer && !skysurfaces && !depthonly)
14541         {
14542                 r_refdef.stats.world_surfaces += numsurfacelist;
14543                 for (j = 0;j < numsurfacelist;j++)
14544                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14545         }
14546
14547         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14548 }
14549
14550 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14551 {
14552         int i, j, endj, flagsmask;
14553         dp_model_t *model = ent->model;
14554         msurface_t *surfaces;
14555         unsigned char *update;
14556         int numsurfacelist = 0;
14557         if (model == NULL)
14558                 return;
14559
14560         if (r_maxsurfacelist < model->num_surfaces)
14561         {
14562                 r_maxsurfacelist = model->num_surfaces;
14563                 if (r_surfacelist)
14564                         Mem_Free((msurface_t **)r_surfacelist);
14565                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14566         }
14567
14568         // if the model is static it doesn't matter what value we give for
14569         // wantnormals and wanttangents, so this logic uses only rules applicable
14570         // to a model, knowing that they are meaningless otherwise
14571         if (ent == r_refdef.scene.worldentity)
14572                 RSurf_ActiveWorldEntity();
14573         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14574                 RSurf_ActiveModelEntity(ent, false, false, false);
14575         else if (prepass)
14576                 RSurf_ActiveModelEntity(ent, true, true, true);
14577         else if (depthonly)
14578         {
14579                 switch (vid.renderpath)
14580                 {
14581                 case RENDERPATH_GL20:
14582                 case RENDERPATH_CGGL:
14583                 case RENDERPATH_D3D9:
14584                 case RENDERPATH_D3D10:
14585                 case RENDERPATH_D3D11:
14586                 case RENDERPATH_SOFT:
14587                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14588                         break;
14589                 case RENDERPATH_GL13:
14590                 case RENDERPATH_GL11:
14591                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14592                         break;
14593                 }
14594         }
14595         else
14596         {
14597                 switch (vid.renderpath)
14598                 {
14599                 case RENDERPATH_GL20:
14600                 case RENDERPATH_CGGL:
14601                 case RENDERPATH_D3D9:
14602                 case RENDERPATH_D3D10:
14603                 case RENDERPATH_D3D11:
14604                 case RENDERPATH_SOFT:
14605                         RSurf_ActiveModelEntity(ent, true, true, false);
14606                         break;
14607                 case RENDERPATH_GL13:
14608                 case RENDERPATH_GL11:
14609                         RSurf_ActiveModelEntity(ent, true, false, false);
14610                         break;
14611                 }
14612         }
14613
14614         surfaces = model->data_surfaces;
14615         update = model->brushq1.lightmapupdateflags;
14616
14617         // update light styles
14618         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14619         {
14620                 model_brush_lightstyleinfo_t *style;
14621                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14622                 {
14623                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14624                         {
14625                                 int *list = style->surfacelist;
14626                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14627                                 for (j = 0;j < style->numsurfaces;j++)
14628                                         update[list[j]] = true;
14629                         }
14630                 }
14631         }
14632
14633         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14634
14635         if (debug)
14636         {
14637                 R_DrawDebugModel();
14638                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14639                 return;
14640         }
14641
14642         rsurface.lightmaptexture = NULL;
14643         rsurface.deluxemaptexture = NULL;
14644         rsurface.uselightmaptexture = false;
14645         rsurface.texture = NULL;
14646         rsurface.rtlight = NULL;
14647         numsurfacelist = 0;
14648         // add visible surfaces to draw list
14649         for (i = 0;i < model->nummodelsurfaces;i++)
14650                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14651         // don't do anything if there were no surfaces
14652         if (!numsurfacelist)
14653         {
14654                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14655                 return;
14656         }
14657         // update lightmaps if needed
14658         if (update)
14659         {
14660                 int updated = 0;
14661                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14662                 {
14663                         if (update[j])
14664                         {
14665                                 updated++;
14666                                 R_BuildLightMap(ent, surfaces + j);
14667                         }
14668                 }
14669         }
14670         if (update)
14671                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14672                         if (update[j])
14673                                 R_BuildLightMap(ent, surfaces + j);
14674         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14675         GL_AlphaTest(false);
14676
14677         // add to stats if desired
14678         if (r_speeds.integer && !skysurfaces && !depthonly)
14679         {
14680                 r_refdef.stats.entities_surfaces += numsurfacelist;
14681                 for (j = 0;j < numsurfacelist;j++)
14682                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14683         }
14684
14685         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14686 }
14687
14688 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14689 {
14690         static texture_t texture;
14691         static msurface_t surface;
14692         const msurface_t *surfacelist = &surface;
14693
14694         // fake enough texture and surface state to render this geometry
14695
14696         texture.update_lastrenderframe = -1; // regenerate this texture
14697         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14698         texture.currentskinframe = skinframe;
14699         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14700         texture.offsetmapping = OFFSETMAPPING_OFF;
14701         texture.offsetscale = 1;
14702         texture.specularscalemod = 1;
14703         texture.specularpowermod = 1;
14704
14705         surface.texture = &texture;
14706         surface.num_triangles = numtriangles;
14707         surface.num_firsttriangle = firsttriangle;
14708         surface.num_vertices = numvertices;
14709         surface.num_firstvertex = firstvertex;
14710
14711         // now render it
14712         rsurface.texture = R_GetCurrentTexture(surface.texture);
14713         rsurface.lightmaptexture = NULL;
14714         rsurface.deluxemaptexture = NULL;
14715         rsurface.uselightmaptexture = false;
14716         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14717 }
14718
14719 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)
14720 {
14721         static msurface_t surface;
14722         const msurface_t *surfacelist = &surface;
14723
14724         // fake enough texture and surface state to render this geometry
14725         surface.texture = texture;
14726         surface.num_triangles = numtriangles;
14727         surface.num_firsttriangle = firsttriangle;
14728         surface.num_vertices = numvertices;
14729         surface.num_firstvertex = firstvertex;
14730
14731         // now render it
14732         rsurface.texture = R_GetCurrentTexture(surface.texture);
14733         rsurface.lightmaptexture = NULL;
14734         rsurface.deluxemaptexture = NULL;
14735         rsurface.uselightmaptexture = false;
14736         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14737 }