]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix two errors related to the R_FrameData_Alloc use in batching
[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] >>= 7;
11913                                         c[1] >>= 7;
11914                                         c[2] >>= 7;
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         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12456         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12457         rsurface.passcolor4f_vertexbuffer = 0;
12458         rsurface.passcolor4f_bufferoffset = 0;
12459         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12460         {
12461                 c2[0] = c[0] * r;
12462                 c2[1] = c[1] * g;
12463                 c2[2] = c[2] * b;
12464                 c2[3] = c[3] * a;
12465         }
12466 }
12467
12468 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12469 {
12470         int i;
12471         const float *c;
12472         float *c2;
12473         if (!rsurface.passcolor4f)
12474                 return;
12475         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12476         rsurface.passcolor4f_vertexbuffer = 0;
12477         rsurface.passcolor4f_bufferoffset = 0;
12478         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12479         {
12480                 c2[0] = c[0] + r_refdef.scene.ambient;
12481                 c2[1] = c[1] + r_refdef.scene.ambient;
12482                 c2[2] = c[2] + r_refdef.scene.ambient;
12483                 c2[3] = c[3];
12484         }
12485 }
12486
12487 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12488 {
12489         // TODO: optimize
12490         rsurface.passcolor4f = NULL;
12491         rsurface.passcolor4f_vertexbuffer = 0;
12492         rsurface.passcolor4f_bufferoffset = 0;
12493         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12494         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12495         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12496         GL_Color(r, g, b, a);
12497         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12498         RSurf_DrawBatch();
12499 }
12500
12501 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12502 {
12503         // TODO: optimize applyfog && applycolor case
12504         // just apply fog if necessary, and tint the fog color array if necessary
12505         rsurface.passcolor4f = NULL;
12506         rsurface.passcolor4f_vertexbuffer = 0;
12507         rsurface.passcolor4f_bufferoffset = 0;
12508         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12509         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12510         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12511         GL_Color(r, g, b, a);
12512         RSurf_DrawBatch();
12513 }
12514
12515 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12516 {
12517         // TODO: optimize
12518         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12519         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12520         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12521         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12522         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12523         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12524         GL_Color(r, g, b, a);
12525         RSurf_DrawBatch();
12526 }
12527
12528 static void RSurf_DrawBatch_GL11_ClampColor(void)
12529 {
12530         int i;
12531         const float *c1;
12532         float *c2;
12533         if (!rsurface.passcolor4f)
12534                 return;
12535         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12536         {
12537                 c2[0] = bound(0.0f, c1[0], 1.0f);
12538                 c2[1] = bound(0.0f, c1[1], 1.0f);
12539                 c2[2] = bound(0.0f, c1[2], 1.0f);
12540                 c2[3] = bound(0.0f, c1[3], 1.0f);
12541         }
12542 }
12543
12544 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12545 {
12546         int i;
12547         float f;
12548         const float *v;
12549         const float *n;
12550         float *c;
12551         //vec3_t eyedir;
12552
12553         // fake shading
12554         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12555         rsurface.passcolor4f_vertexbuffer = 0;
12556         rsurface.passcolor4f_bufferoffset = 0;
12557         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)
12558         {
12559                 f = -DotProduct(r_refdef.view.forward, n);
12560                 f = max(0, f);
12561                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12562                 f *= r_refdef.lightmapintensity;
12563                 Vector4Set(c, f, f, f, 1);
12564         }
12565 }
12566
12567 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12568 {
12569         RSurf_DrawBatch_GL11_ApplyFakeLight();
12570         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12571         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12572         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12573         GL_Color(r, g, b, a);
12574         RSurf_DrawBatch();
12575 }
12576
12577 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12578 {
12579         int i;
12580         float f;
12581         float alpha;
12582         const float *v;
12583         const float *n;
12584         float *c;
12585         vec3_t ambientcolor;
12586         vec3_t diffusecolor;
12587         vec3_t lightdir;
12588         // TODO: optimize
12589         // model lighting
12590         VectorCopy(rsurface.modellight_lightdir, lightdir);
12591         f = 0.5f * r_refdef.lightmapintensity;
12592         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12593         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12594         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12595         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12596         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12597         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12598         alpha = *a;
12599         if (VectorLength2(diffusecolor) > 0)
12600         {
12601                 // q3-style directional shading
12602                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12603                 rsurface.passcolor4f_vertexbuffer = 0;
12604                 rsurface.passcolor4f_bufferoffset = 0;
12605                 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)
12606                 {
12607                         if ((f = DotProduct(n, lightdir)) > 0)
12608                                 VectorMA(ambientcolor, f, diffusecolor, c);
12609                         else
12610                                 VectorCopy(ambientcolor, c);
12611                         c[3] = alpha;
12612                 }
12613                 *r = 1;
12614                 *g = 1;
12615                 *b = 1;
12616                 *a = 1;
12617                 *applycolor = false;
12618         }
12619         else
12620         {
12621                 *r = ambientcolor[0];
12622                 *g = ambientcolor[1];
12623                 *b = ambientcolor[2];
12624                 rsurface.passcolor4f = NULL;
12625                 rsurface.passcolor4f_vertexbuffer = 0;
12626                 rsurface.passcolor4f_bufferoffset = 0;
12627         }
12628 }
12629
12630 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12631 {
12632         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12633         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12634         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12635         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12636         GL_Color(r, g, b, a);
12637         RSurf_DrawBatch();
12638 }
12639
12640 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12641 {
12642         int i;
12643         float f;
12644         const float *v;
12645         float *c;
12646         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12647         {
12648                 f = 1 - RSurf_FogVertex(v);
12649                 c[0] = r;
12650                 c[1] = g;
12651                 c[2] = b;
12652                 c[3] = f * a;
12653         }
12654 }
12655
12656 void RSurf_SetupDepthAndCulling(void)
12657 {
12658         // submodels are biased to avoid z-fighting with world surfaces that they
12659         // may be exactly overlapping (avoids z-fighting artifacts on certain
12660         // doors and things in Quake maps)
12661         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12662         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12663         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12664         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12665 }
12666
12667 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12668 {
12669         // transparent sky would be ridiculous
12670         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12671                 return;
12672         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12673         skyrenderlater = true;
12674         RSurf_SetupDepthAndCulling();
12675         GL_DepthMask(true);
12676         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12677         // skymasking on them, and Quake3 never did sky masking (unlike
12678         // software Quake and software Quake2), so disable the sky masking
12679         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12680         // and skymasking also looks very bad when noclipping outside the
12681         // level, so don't use it then either.
12682         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12683         {
12684                 R_Mesh_ResetTextureState();
12685                 if (skyrendermasked)
12686                 {
12687                         R_SetupShader_DepthOrShadow();
12688                         // depth-only (masking)
12689                         GL_ColorMask(0,0,0,0);
12690                         // just to make sure that braindead drivers don't draw
12691                         // anything despite that colormask...
12692                         GL_BlendFunc(GL_ZERO, GL_ONE);
12693                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12694                         if (rsurface.batchvertex3fbuffer)
12695                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12696                         else
12697                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12698                 }
12699                 else
12700                 {
12701                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12702                         // fog sky
12703                         GL_BlendFunc(GL_ONE, GL_ZERO);
12704                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12705                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12706                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12707                 }
12708                 RSurf_DrawBatch();
12709                 if (skyrendermasked)
12710                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12711         }
12712         R_Mesh_ResetTextureState();
12713         GL_Color(1, 1, 1, 1);
12714 }
12715
12716 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12717 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12718 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12719 {
12720         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12721                 return;
12722         if (prepass)
12723         {
12724                 // render screenspace normalmap to texture
12725                 GL_DepthMask(true);
12726                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12727                 RSurf_DrawBatch();
12728                 return;
12729         }
12730
12731         // bind lightmap texture
12732
12733         // water/refraction/reflection/camera surfaces have to be handled specially
12734         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12735         {
12736                 int start, end, startplaneindex;
12737                 for (start = 0;start < texturenumsurfaces;start = end)
12738                 {
12739                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12740                         if(startplaneindex < 0)
12741                         {
12742                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12743                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12744                                 end = start + 1;
12745                                 continue;
12746                         }
12747                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12748                                 ;
12749                         // now that we have a batch using the same planeindex, render it
12750                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12751                         {
12752                                 // render water or distortion background
12753                                 GL_DepthMask(true);
12754                                 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));
12755                                 RSurf_DrawBatch();
12756                                 // blend surface on top
12757                                 GL_DepthMask(false);
12758                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12759                                 RSurf_DrawBatch();
12760                         }
12761                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12762                         {
12763                                 // render surface with reflection texture as input
12764                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12765                                 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));
12766                                 RSurf_DrawBatch();
12767                         }
12768                 }
12769                 return;
12770         }
12771
12772         // render surface batch normally
12773         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12774         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12775         RSurf_DrawBatch();
12776 }
12777
12778 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12779 {
12780         // OpenGL 1.3 path - anything not completely ancient
12781         qboolean applycolor;
12782         qboolean applyfog;
12783         int layerindex;
12784         const texturelayer_t *layer;
12785         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);
12786         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12787
12788         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12789         {
12790                 vec4_t layercolor;
12791                 int layertexrgbscale;
12792                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12793                 {
12794                         if (layerindex == 0)
12795                                 GL_AlphaTest(true);
12796                         else
12797                         {
12798                                 GL_AlphaTest(false);
12799                                 GL_DepthFunc(GL_EQUAL);
12800                         }
12801                 }
12802                 GL_DepthMask(layer->depthmask && writedepth);
12803                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12804                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12805                 {
12806                         layertexrgbscale = 4;
12807                         VectorScale(layer->color, 0.25f, layercolor);
12808                 }
12809                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12810                 {
12811                         layertexrgbscale = 2;
12812                         VectorScale(layer->color, 0.5f, layercolor);
12813                 }
12814                 else
12815                 {
12816                         layertexrgbscale = 1;
12817                         VectorScale(layer->color, 1.0f, layercolor);
12818                 }
12819                 layercolor[3] = layer->color[3];
12820                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12821                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12822                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12823                 switch (layer->type)
12824                 {
12825                 case TEXTURELAYERTYPE_LITTEXTURE:
12826                         // single-pass lightmapped texture with 2x rgbscale
12827                         R_Mesh_TexBind(0, r_texture_white);
12828                         R_Mesh_TexMatrix(0, NULL);
12829                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12830                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12831                         R_Mesh_TexBind(1, layer->texture);
12832                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12833                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12834                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12835                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12836                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12837                         else if (FAKELIGHT_ENABLED)
12838                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12839                         else if (rsurface.uselightmaptexture)
12840                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12841                         else
12842                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12843                         break;
12844                 case TEXTURELAYERTYPE_TEXTURE:
12845                         // singletexture unlit texture with transparency support
12846                         R_Mesh_TexBind(0, layer->texture);
12847                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12848                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12849                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12850                         R_Mesh_TexBind(1, 0);
12851                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12852                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12853                         break;
12854                 case TEXTURELAYERTYPE_FOG:
12855                         // singletexture fogging
12856                         if (layer->texture)
12857                         {
12858                                 R_Mesh_TexBind(0, layer->texture);
12859                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12860                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12861                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12862                         }
12863                         else
12864                         {
12865                                 R_Mesh_TexBind(0, 0);
12866                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12867                         }
12868                         R_Mesh_TexBind(1, 0);
12869                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12870                         // generate a color array for the fog pass
12871                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12872                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12873                         RSurf_DrawBatch();
12874                         break;
12875                 default:
12876                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12877                 }
12878         }
12879         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12880         {
12881                 GL_DepthFunc(GL_LEQUAL);
12882                 GL_AlphaTest(false);
12883         }
12884 }
12885
12886 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12887 {
12888         // OpenGL 1.1 - crusty old voodoo path
12889         qboolean applyfog;
12890         int layerindex;
12891         const texturelayer_t *layer;
12892         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);
12893         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12894
12895         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12896         {
12897                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12898                 {
12899                         if (layerindex == 0)
12900                                 GL_AlphaTest(true);
12901                         else
12902                         {
12903                                 GL_AlphaTest(false);
12904                                 GL_DepthFunc(GL_EQUAL);
12905                         }
12906                 }
12907                 GL_DepthMask(layer->depthmask && writedepth);
12908                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12909                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12910                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12911                 switch (layer->type)
12912                 {
12913                 case TEXTURELAYERTYPE_LITTEXTURE:
12914                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12915                         {
12916                                 // two-pass lit texture with 2x rgbscale
12917                                 // first the lightmap pass
12918                                 R_Mesh_TexBind(0, r_texture_white);
12919                                 R_Mesh_TexMatrix(0, NULL);
12920                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12921                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12922                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12923                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12924                                 else if (FAKELIGHT_ENABLED)
12925                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12926                                 else if (rsurface.uselightmaptexture)
12927                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12928                                 else
12929                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12930                                 // then apply the texture to it
12931                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12932                                 R_Mesh_TexBind(0, layer->texture);
12933                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12934                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12935                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12936                                 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);
12937                         }
12938                         else
12939                         {
12940                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12941                                 R_Mesh_TexBind(0, layer->texture);
12942                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12943                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12944                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12945                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12946                                         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);
12947                                 else
12948                                         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);
12949                         }
12950                         break;
12951                 case TEXTURELAYERTYPE_TEXTURE:
12952                         // singletexture unlit texture with transparency support
12953                         R_Mesh_TexBind(0, layer->texture);
12954                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12955                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12956                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12957                         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);
12958                         break;
12959                 case TEXTURELAYERTYPE_FOG:
12960                         // singletexture fogging
12961                         if (layer->texture)
12962                         {
12963                                 R_Mesh_TexBind(0, layer->texture);
12964                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12965                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12966                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12967                         }
12968                         else
12969                         {
12970                                 R_Mesh_TexBind(0, 0);
12971                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12972                         }
12973                         // generate a color array for the fog pass
12974                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12975                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12976                         RSurf_DrawBatch();
12977                         break;
12978                 default:
12979                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12980                 }
12981         }
12982         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12983         {
12984                 GL_DepthFunc(GL_LEQUAL);
12985                 GL_AlphaTest(false);
12986         }
12987 }
12988
12989 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12990 {
12991         int vi;
12992         int j;
12993         r_vertexgeneric_t *batchvertex;
12994         float c[4];
12995
12996         GL_AlphaTest(false);
12997 //      R_Mesh_ResetTextureState();
12998         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12999
13000         if(rsurface.texture && rsurface.texture->currentskinframe)
13001         {
13002                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
13003                 c[3] *= rsurface.texture->currentalpha;
13004         }
13005         else
13006         {
13007                 c[0] = 1;
13008                 c[1] = 0;
13009                 c[2] = 1;
13010                 c[3] = 1;
13011         }
13012
13013         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
13014         {
13015                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
13016                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
13017                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
13018         }
13019
13020         // brighten it up (as texture value 127 means "unlit")
13021         c[0] *= 2 * r_refdef.view.colorscale;
13022         c[1] *= 2 * r_refdef.view.colorscale;
13023         c[2] *= 2 * r_refdef.view.colorscale;
13024
13025         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
13026                 c[3] *= r_wateralpha.value;
13027
13028         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
13029         {
13030                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13031                 GL_DepthMask(false);
13032         }
13033         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
13034         {
13035                 GL_BlendFunc(GL_ONE, GL_ONE);
13036                 GL_DepthMask(false);
13037         }
13038         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13039         {
13040                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
13041                 GL_DepthMask(false);
13042         }
13043         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
13044         {
13045                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
13046                 GL_DepthMask(false);
13047         }
13048         else
13049         {
13050                 GL_BlendFunc(GL_ONE, GL_ZERO);
13051                 GL_DepthMask(writedepth);
13052         }
13053
13054         if (r_showsurfaces.integer == 3)
13055         {
13056                 rsurface.passcolor4f = NULL;
13057
13058                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
13059                 {
13060                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13061
13062                         rsurface.passcolor4f = NULL;
13063                         rsurface.passcolor4f_vertexbuffer = 0;
13064                         rsurface.passcolor4f_bufferoffset = 0;
13065                 }
13066                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13067                 {
13068                         qboolean applycolor = true;
13069                         float one = 1.0;
13070
13071                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13072
13073                         r_refdef.lightmapintensity = 1;
13074                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
13075                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13076                 }
13077                 else if (FAKELIGHT_ENABLED)
13078                 {
13079                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13080
13081                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
13082                         RSurf_DrawBatch_GL11_ApplyFakeLight();
13083                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13084                 }
13085                 else
13086                 {
13087                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13088
13089                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13090                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13091                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13092                 }
13093
13094                 if(!rsurface.passcolor4f)
13095                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13096
13097                 RSurf_DrawBatch_GL11_ApplyAmbient();
13098                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13099                 if(r_refdef.fogenabled)
13100                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13101                 RSurf_DrawBatch_GL11_ClampColor();
13102
13103                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13104                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13105                 RSurf_DrawBatch();
13106         }
13107         else if (!r_refdef.view.showdebug)
13108         {
13109                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13110                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13111                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13112                 {
13113                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13114                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13115                 }
13116                 R_Mesh_PrepareVertices_Generic_Unlock();
13117                 RSurf_DrawBatch();
13118         }
13119         else if (r_showsurfaces.integer == 4)
13120         {
13121                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13122                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13123                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13124                 {
13125                         unsigned char c = vi << 3;
13126                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13127                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13128                 }
13129                 R_Mesh_PrepareVertices_Generic_Unlock();
13130                 RSurf_DrawBatch();
13131         }
13132         else if (r_showsurfaces.integer == 2)
13133         {
13134                 const int *e;
13135                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13136                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13137                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13138                 {
13139                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13140                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13141                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13142                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13143                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13144                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13145                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13146                 }
13147                 R_Mesh_PrepareVertices_Generic_Unlock();
13148                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13149         }
13150         else
13151         {
13152                 int texturesurfaceindex;
13153                 int k;
13154                 const msurface_t *surface;
13155                 unsigned char surfacecolor4ub[4];
13156                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13157                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13158                 vi = 0;
13159                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13160                 {
13161                         surface = texturesurfacelist[texturesurfaceindex];
13162                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13163                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13164                         for (j = 0;j < surface->num_vertices;j++)
13165                         {
13166                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13167                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13168                                 vi++;
13169                         }
13170                 }
13171                 R_Mesh_PrepareVertices_Generic_Unlock();
13172                 RSurf_DrawBatch();
13173         }
13174 }
13175
13176 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13177 {
13178         CHECKGLERROR
13179         RSurf_SetupDepthAndCulling();
13180         if (r_showsurfaces.integer)
13181         {
13182                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13183                 return;
13184         }
13185         switch (vid.renderpath)
13186         {
13187         case RENDERPATH_GL20:
13188         case RENDERPATH_CGGL:
13189         case RENDERPATH_D3D9:
13190         case RENDERPATH_D3D10:
13191         case RENDERPATH_D3D11:
13192         case RENDERPATH_SOFT:
13193                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13194                 break;
13195         case RENDERPATH_GL13:
13196                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13197                 break;
13198         case RENDERPATH_GL11:
13199                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13200                 break;
13201         }
13202         CHECKGLERROR
13203 }
13204
13205 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13206 {
13207         CHECKGLERROR
13208         RSurf_SetupDepthAndCulling();
13209         if (r_showsurfaces.integer)
13210         {
13211                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13212                 return;
13213         }
13214         switch (vid.renderpath)
13215         {
13216         case RENDERPATH_GL20:
13217         case RENDERPATH_CGGL:
13218         case RENDERPATH_D3D9:
13219         case RENDERPATH_D3D10:
13220         case RENDERPATH_D3D11:
13221         case RENDERPATH_SOFT:
13222                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13223                 break;
13224         case RENDERPATH_GL13:
13225                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13226                 break;
13227         case RENDERPATH_GL11:
13228                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13229                 break;
13230         }
13231         CHECKGLERROR
13232 }
13233
13234 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13235 {
13236         int i, j;
13237         int texturenumsurfaces, endsurface;
13238         texture_t *texture;
13239         const msurface_t *surface;
13240 #define MAXBATCH_TRANSPARENTSURFACES 256
13241         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13242
13243         // if the model is static it doesn't matter what value we give for
13244         // wantnormals and wanttangents, so this logic uses only rules applicable
13245         // to a model, knowing that they are meaningless otherwise
13246         if (ent == r_refdef.scene.worldentity)
13247                 RSurf_ActiveWorldEntity();
13248         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13249                 RSurf_ActiveModelEntity(ent, false, false, false);
13250         else
13251         {
13252                 switch (vid.renderpath)
13253                 {
13254                 case RENDERPATH_GL20:
13255                 case RENDERPATH_CGGL:
13256                 case RENDERPATH_D3D9:
13257                 case RENDERPATH_D3D10:
13258                 case RENDERPATH_D3D11:
13259                 case RENDERPATH_SOFT:
13260                         RSurf_ActiveModelEntity(ent, true, true, false);
13261                         break;
13262                 case RENDERPATH_GL13:
13263                 case RENDERPATH_GL11:
13264                         RSurf_ActiveModelEntity(ent, true, false, false);
13265                         break;
13266                 }
13267         }
13268
13269         if (r_transparentdepthmasking.integer)
13270         {
13271                 qboolean setup = false;
13272                 for (i = 0;i < numsurfaces;i = j)
13273                 {
13274                         j = i + 1;
13275                         surface = rsurface.modelsurfaces + surfacelist[i];
13276                         texture = surface->texture;
13277                         rsurface.texture = R_GetCurrentTexture(texture);
13278                         rsurface.lightmaptexture = NULL;
13279                         rsurface.deluxemaptexture = NULL;
13280                         rsurface.uselightmaptexture = false;
13281                         // scan ahead until we find a different texture
13282                         endsurface = min(i + 1024, numsurfaces);
13283                         texturenumsurfaces = 0;
13284                         texturesurfacelist[texturenumsurfaces++] = surface;
13285                         for (;j < endsurface;j++)
13286                         {
13287                                 surface = rsurface.modelsurfaces + surfacelist[j];
13288                                 if (texture != surface->texture)
13289                                         break;
13290                                 texturesurfacelist[texturenumsurfaces++] = surface;
13291                         }
13292                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13293                                 continue;
13294                         // render the range of surfaces as depth
13295                         if (!setup)
13296                         {
13297                                 setup = true;
13298                                 GL_ColorMask(0,0,0,0);
13299                                 GL_Color(1,1,1,1);
13300                                 GL_DepthTest(true);
13301                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13302                                 GL_DepthMask(true);
13303                                 GL_AlphaTest(false);
13304 //                              R_Mesh_ResetTextureState();
13305                                 R_SetupShader_DepthOrShadow();
13306                         }
13307                         RSurf_SetupDepthAndCulling();
13308                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13309                         if (rsurface.batchvertex3fbuffer)
13310                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13311                         else
13312                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13313                         RSurf_DrawBatch();
13314                 }
13315                 if (setup)
13316                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13317         }
13318
13319         for (i = 0;i < numsurfaces;i = j)
13320         {
13321                 j = i + 1;
13322                 surface = rsurface.modelsurfaces + surfacelist[i];
13323                 texture = surface->texture;
13324                 rsurface.texture = R_GetCurrentTexture(texture);
13325                 // scan ahead until we find a different texture
13326                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13327                 texturenumsurfaces = 0;
13328                 texturesurfacelist[texturenumsurfaces++] = surface;
13329                 if(FAKELIGHT_ENABLED)
13330                 {
13331                         rsurface.lightmaptexture = NULL;
13332                         rsurface.deluxemaptexture = NULL;
13333                         rsurface.uselightmaptexture = false;
13334                         for (;j < endsurface;j++)
13335                         {
13336                                 surface = rsurface.modelsurfaces + surfacelist[j];
13337                                 if (texture != surface->texture)
13338                                         break;
13339                                 texturesurfacelist[texturenumsurfaces++] = surface;
13340                         }
13341                 }
13342                 else
13343                 {
13344                         rsurface.lightmaptexture = surface->lightmaptexture;
13345                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13346                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13347                         for (;j < endsurface;j++)
13348                         {
13349                                 surface = rsurface.modelsurfaces + surfacelist[j];
13350                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13351                                         break;
13352                                 texturesurfacelist[texturenumsurfaces++] = surface;
13353                         }
13354                 }
13355                 // render the range of surfaces
13356                 if (ent == r_refdef.scene.worldentity)
13357                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13358                 else
13359                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13360         }
13361         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13362         GL_AlphaTest(false);
13363 }
13364
13365 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13366 {
13367         // transparent surfaces get pushed off into the transparent queue
13368         int surfacelistindex;
13369         const msurface_t *surface;
13370         vec3_t tempcenter, center;
13371         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13372         {
13373                 surface = texturesurfacelist[surfacelistindex];
13374                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13375                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13376                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13377                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13378                 if (queueentity->transparent_offset) // transparent offset
13379                 {
13380                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13381                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13382                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13383                 }
13384                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13385         }
13386 }
13387
13388 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13389 {
13390         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13391                 return;
13392         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13393                 return;
13394         RSurf_SetupDepthAndCulling();
13395         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13396         if (rsurface.batchvertex3fbuffer)
13397                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13398         else
13399                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13400         RSurf_DrawBatch();
13401 }
13402
13403 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13404 {
13405         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13406         CHECKGLERROR
13407         if (depthonly)
13408                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13409         else if (prepass)
13410         {
13411                 if (!rsurface.texture->currentnumlayers)
13412                         return;
13413                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13414                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13415                 else
13416                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13417         }
13418         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13419                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13420         else if (!rsurface.texture->currentnumlayers)
13421                 return;
13422         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13423         {
13424                 // in the deferred case, transparent surfaces were queued during prepass
13425                 if (!r_shadow_usingdeferredprepass)
13426                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13427         }
13428         else
13429         {
13430                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13431                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13432         }
13433         CHECKGLERROR
13434 }
13435
13436 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13437 {
13438         int i, j;
13439         texture_t *texture;
13440         R_FrameData_SetMark();
13441         // break the surface list down into batches by texture and use of lightmapping
13442         for (i = 0;i < numsurfaces;i = j)
13443         {
13444                 j = i + 1;
13445                 // texture is the base texture pointer, rsurface.texture is the
13446                 // current frame/skin the texture is directing us to use (for example
13447                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13448                 // use skin 1 instead)
13449                 texture = surfacelist[i]->texture;
13450                 rsurface.texture = R_GetCurrentTexture(texture);
13451                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13452                 {
13453                         // if this texture is not the kind we want, skip ahead to the next one
13454                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13455                                 ;
13456                         continue;
13457                 }
13458                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13459                 {
13460                         rsurface.lightmaptexture = NULL;
13461                         rsurface.deluxemaptexture = NULL;
13462                         rsurface.uselightmaptexture = false;
13463                         // simply scan ahead until we find a different texture or lightmap state
13464                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13465                                 ;
13466                 }
13467                 else
13468                 {
13469                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13470                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13471                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13472                         // simply scan ahead until we find a different texture or lightmap state
13473                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13474                                 ;
13475                 }
13476                 // render the range of surfaces
13477                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13478         }
13479         R_FrameData_ReturnToMark();
13480 }
13481
13482 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13483 {
13484         CHECKGLERROR
13485         if (depthonly)
13486                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13487         else if (prepass)
13488         {
13489                 if (!rsurface.texture->currentnumlayers)
13490                         return;
13491                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13492                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13493                 else
13494                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13495         }
13496         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13497                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13498         else if (!rsurface.texture->currentnumlayers)
13499                 return;
13500         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13501         {
13502                 // in the deferred case, transparent surfaces were queued during prepass
13503                 if (!r_shadow_usingdeferredprepass)
13504                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13505         }
13506         else
13507         {
13508                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13509                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13510         }
13511         CHECKGLERROR
13512 }
13513
13514 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13515 {
13516         int i, j;
13517         texture_t *texture;
13518         R_FrameData_SetMark();
13519         // break the surface list down into batches by texture and use of lightmapping
13520         for (i = 0;i < numsurfaces;i = j)
13521         {
13522                 j = i + 1;
13523                 // texture is the base texture pointer, rsurface.texture is the
13524                 // current frame/skin the texture is directing us to use (for example
13525                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13526                 // use skin 1 instead)
13527                 texture = surfacelist[i]->texture;
13528                 rsurface.texture = R_GetCurrentTexture(texture);
13529                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13530                 {
13531                         // if this texture is not the kind we want, skip ahead to the next one
13532                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13533                                 ;
13534                         continue;
13535                 }
13536                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13537                 {
13538                         rsurface.lightmaptexture = NULL;
13539                         rsurface.deluxemaptexture = NULL;
13540                         rsurface.uselightmaptexture = false;
13541                         // simply scan ahead until we find a different texture or lightmap state
13542                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13543                                 ;
13544                 }
13545                 else
13546                 {
13547                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13548                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13549                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13550                         // simply scan ahead until we find a different texture or lightmap state
13551                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13552                                 ;
13553                 }
13554                 // render the range of surfaces
13555                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13556         }
13557         R_FrameData_ReturnToMark();
13558 }
13559
13560 float locboxvertex3f[6*4*3] =
13561 {
13562         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13563         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13564         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13565         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13566         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13567         1,0,0, 0,0,0, 0,1,0, 1,1,0
13568 };
13569
13570 unsigned short locboxelements[6*2*3] =
13571 {
13572          0, 1, 2, 0, 2, 3,
13573          4, 5, 6, 4, 6, 7,
13574          8, 9,10, 8,10,11,
13575         12,13,14, 12,14,15,
13576         16,17,18, 16,18,19,
13577         20,21,22, 20,22,23
13578 };
13579
13580 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13581 {
13582         int i, j;
13583         cl_locnode_t *loc = (cl_locnode_t *)ent;
13584         vec3_t mins, size;
13585         float vertex3f[6*4*3];
13586         CHECKGLERROR
13587         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13588         GL_DepthMask(false);
13589         GL_DepthRange(0, 1);
13590         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13591         GL_DepthTest(true);
13592         GL_CullFace(GL_NONE);
13593         R_EntityMatrix(&identitymatrix);
13594
13595 //      R_Mesh_ResetTextureState();
13596
13597         i = surfacelist[0];
13598         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13599                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13600                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13601                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13602
13603         if (VectorCompare(loc->mins, loc->maxs))
13604         {
13605                 VectorSet(size, 2, 2, 2);
13606                 VectorMA(loc->mins, -0.5f, size, mins);
13607         }
13608         else
13609         {
13610                 VectorCopy(loc->mins, mins);
13611                 VectorSubtract(loc->maxs, loc->mins, size);
13612         }
13613
13614         for (i = 0;i < 6*4*3;)
13615                 for (j = 0;j < 3;j++, i++)
13616                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13617
13618         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13619         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13620         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13621 }
13622
13623 void R_DrawLocs(void)
13624 {
13625         int index;
13626         cl_locnode_t *loc, *nearestloc;
13627         vec3_t center;
13628         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13629         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13630         {
13631                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13632                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13633         }
13634 }
13635
13636 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13637 {
13638         if (decalsystem->decals)
13639                 Mem_Free(decalsystem->decals);
13640         memset(decalsystem, 0, sizeof(*decalsystem));
13641 }
13642
13643 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)
13644 {
13645         tridecal_t *decal;
13646         tridecal_t *decals;
13647         int i;
13648
13649         // expand or initialize the system
13650         if (decalsystem->maxdecals <= decalsystem->numdecals)
13651         {
13652                 decalsystem_t old = *decalsystem;
13653                 qboolean useshortelements;
13654                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13655                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13656                 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)));
13657                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13658                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13659                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13660                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13661                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13662                 if (decalsystem->numdecals)
13663                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13664                 if (old.decals)
13665                         Mem_Free(old.decals);
13666                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13667                         decalsystem->element3i[i] = i;
13668                 if (useshortelements)
13669                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13670                                 decalsystem->element3s[i] = i;
13671         }
13672
13673         // grab a decal and search for another free slot for the next one
13674         decals = decalsystem->decals;
13675         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13676         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13677                 ;
13678         decalsystem->freedecal = i;
13679         if (decalsystem->numdecals <= i)
13680                 decalsystem->numdecals = i + 1;
13681
13682         // initialize the decal
13683         decal->lived = 0;
13684         decal->triangleindex = triangleindex;
13685         decal->surfaceindex = surfaceindex;
13686         decal->decalsequence = decalsequence;
13687         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13688         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13689         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13690         decal->color4ub[0][3] = 255;
13691         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13692         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13693         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13694         decal->color4ub[1][3] = 255;
13695         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13696         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13697         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13698         decal->color4ub[2][3] = 255;
13699         decal->vertex3f[0][0] = v0[0];
13700         decal->vertex3f[0][1] = v0[1];
13701         decal->vertex3f[0][2] = v0[2];
13702         decal->vertex3f[1][0] = v1[0];
13703         decal->vertex3f[1][1] = v1[1];
13704         decal->vertex3f[1][2] = v1[2];
13705         decal->vertex3f[2][0] = v2[0];
13706         decal->vertex3f[2][1] = v2[1];
13707         decal->vertex3f[2][2] = v2[2];
13708         decal->texcoord2f[0][0] = t0[0];
13709         decal->texcoord2f[0][1] = t0[1];
13710         decal->texcoord2f[1][0] = t1[0];
13711         decal->texcoord2f[1][1] = t1[1];
13712         decal->texcoord2f[2][0] = t2[0];
13713         decal->texcoord2f[2][1] = t2[1];
13714 }
13715
13716 extern cvar_t cl_decals_bias;
13717 extern cvar_t cl_decals_models;
13718 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13719 // baseparms, parms, temps
13720 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)
13721 {
13722         int cornerindex;
13723         int index;
13724         float v[9][3];
13725         const float *vertex3f;
13726         int numpoints;
13727         float points[2][9][3];
13728         float temp[3];
13729         float tc[9][2];
13730         float f;
13731         float c[9][4];
13732         const int *e;
13733
13734         e = rsurface.modelelement3i + 3*triangleindex;
13735
13736         vertex3f = rsurface.modelvertex3f;
13737
13738         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13739         {
13740                 index = 3*e[cornerindex];
13741                 VectorCopy(vertex3f + index, v[cornerindex]);
13742         }
13743         // cull backfaces
13744         //TriangleNormal(v[0], v[1], v[2], normal);
13745         //if (DotProduct(normal, localnormal) < 0.0f)
13746         //      continue;
13747         // clip by each of the box planes formed from the projection matrix
13748         // if anything survives, we emit the decal
13749         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]);
13750         if (numpoints < 3)
13751                 return;
13752         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]);
13753         if (numpoints < 3)
13754                 return;
13755         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]);
13756         if (numpoints < 3)
13757                 return;
13758         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]);
13759         if (numpoints < 3)
13760                 return;
13761         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]);
13762         if (numpoints < 3)
13763                 return;
13764         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]);
13765         if (numpoints < 3)
13766                 return;
13767         // some part of the triangle survived, so we have to accept it...
13768         if (dynamic)
13769         {
13770                 // dynamic always uses the original triangle
13771                 numpoints = 3;
13772                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13773                 {
13774                         index = 3*e[cornerindex];
13775                         VectorCopy(vertex3f + index, v[cornerindex]);
13776                 }
13777         }
13778         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13779         {
13780                 // convert vertex positions to texcoords
13781                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13782                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13783                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13784                 // calculate distance fade from the projection origin
13785                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13786                 f = bound(0.0f, f, 1.0f);
13787                 c[cornerindex][0] = r * f;
13788                 c[cornerindex][1] = g * f;
13789                 c[cornerindex][2] = b * f;
13790                 c[cornerindex][3] = 1.0f;
13791                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13792         }
13793         if (dynamic)
13794                 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);
13795         else
13796                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13797                         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);
13798 }
13799 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)
13800 {
13801         matrix4x4_t projection;
13802         decalsystem_t *decalsystem;
13803         qboolean dynamic;
13804         dp_model_t *model;
13805         const msurface_t *surface;
13806         const msurface_t *surfaces;
13807         const int *surfacelist;
13808         const texture_t *texture;
13809         int numtriangles;
13810         int numsurfacelist;
13811         int surfacelistindex;
13812         int surfaceindex;
13813         int triangleindex;
13814         float localorigin[3];
13815         float localnormal[3];
13816         float localmins[3];
13817         float localmaxs[3];
13818         float localsize;
13819         //float normal[3];
13820         float planes[6][4];
13821         float angles[3];
13822         bih_t *bih;
13823         int bih_triangles_count;
13824         int bih_triangles[256];
13825         int bih_surfaces[256];
13826
13827         decalsystem = &ent->decalsystem;
13828         model = ent->model;
13829         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13830         {
13831                 R_DecalSystem_Reset(&ent->decalsystem);
13832                 return;
13833         }
13834
13835         if (!model->brush.data_leafs && !cl_decals_models.integer)
13836         {
13837                 if (decalsystem->model)
13838                         R_DecalSystem_Reset(decalsystem);
13839                 return;
13840         }
13841
13842         if (decalsystem->model != model)
13843                 R_DecalSystem_Reset(decalsystem);
13844         decalsystem->model = model;
13845
13846         RSurf_ActiveModelEntity(ent, false, false, false);
13847
13848         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13849         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13850         VectorNormalize(localnormal);
13851         localsize = worldsize*rsurface.inversematrixscale;
13852         localmins[0] = localorigin[0] - localsize;
13853         localmins[1] = localorigin[1] - localsize;
13854         localmins[2] = localorigin[2] - localsize;
13855         localmaxs[0] = localorigin[0] + localsize;
13856         localmaxs[1] = localorigin[1] + localsize;
13857         localmaxs[2] = localorigin[2] + localsize;
13858
13859         //VectorCopy(localnormal, planes[4]);
13860         //VectorVectors(planes[4], planes[2], planes[0]);
13861         AnglesFromVectors(angles, localnormal, NULL, false);
13862         AngleVectors(angles, planes[0], planes[2], planes[4]);
13863         VectorNegate(planes[0], planes[1]);
13864         VectorNegate(planes[2], planes[3]);
13865         VectorNegate(planes[4], planes[5]);
13866         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13867         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13868         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13869         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13870         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13871         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13872
13873 #if 1
13874 // works
13875 {
13876         matrix4x4_t forwardprojection;
13877         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13878         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13879 }
13880 #else
13881 // broken
13882 {
13883         float projectionvector[4][3];
13884         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13885         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13886         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13887         projectionvector[0][0] = planes[0][0] * ilocalsize;
13888         projectionvector[0][1] = planes[1][0] * ilocalsize;
13889         projectionvector[0][2] = planes[2][0] * ilocalsize;
13890         projectionvector[1][0] = planes[0][1] * ilocalsize;
13891         projectionvector[1][1] = planes[1][1] * ilocalsize;
13892         projectionvector[1][2] = planes[2][1] * ilocalsize;
13893         projectionvector[2][0] = planes[0][2] * ilocalsize;
13894         projectionvector[2][1] = planes[1][2] * ilocalsize;
13895         projectionvector[2][2] = planes[2][2] * ilocalsize;
13896         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13897         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13898         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13899         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13900 }
13901 #endif
13902
13903         dynamic = model->surfmesh.isanimated;
13904         numsurfacelist = model->nummodelsurfaces;
13905         surfacelist = model->sortedmodelsurfaces;
13906         surfaces = model->data_surfaces;
13907
13908         bih = NULL;
13909         bih_triangles_count = -1;
13910         if(!dynamic)
13911         {
13912                 if(model->render_bih.numleafs)
13913                         bih = &model->render_bih;
13914                 else if(model->collision_bih.numleafs)
13915                         bih = &model->collision_bih;
13916         }
13917         if(bih)
13918                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13919         if(bih_triangles_count == 0)
13920                 return;
13921         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13922                 return;
13923         if(bih_triangles_count > 0)
13924         {
13925                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13926                 {
13927                         surfaceindex = bih_surfaces[triangleindex];
13928                         surface = surfaces + surfaceindex;
13929                         texture = surface->texture;
13930                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13931                                 continue;
13932                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13933                                 continue;
13934                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13935                 }
13936         }
13937         else
13938         {
13939                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13940                 {
13941                         surfaceindex = surfacelist[surfacelistindex];
13942                         surface = surfaces + surfaceindex;
13943                         // check cull box first because it rejects more than any other check
13944                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13945                                 continue;
13946                         // skip transparent surfaces
13947                         texture = surface->texture;
13948                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13949                                 continue;
13950                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13951                                 continue;
13952                         numtriangles = surface->num_triangles;
13953                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13954                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13955                 }
13956         }
13957 }
13958
13959 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13960 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)
13961 {
13962         int renderentityindex;
13963         float worldmins[3];
13964         float worldmaxs[3];
13965         entity_render_t *ent;
13966
13967         if (!cl_decals_newsystem.integer)
13968                 return;
13969
13970         worldmins[0] = worldorigin[0] - worldsize;
13971         worldmins[1] = worldorigin[1] - worldsize;
13972         worldmins[2] = worldorigin[2] - worldsize;
13973         worldmaxs[0] = worldorigin[0] + worldsize;
13974         worldmaxs[1] = worldorigin[1] + worldsize;
13975         worldmaxs[2] = worldorigin[2] + worldsize;
13976
13977         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13978
13979         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13980         {
13981                 ent = r_refdef.scene.entities[renderentityindex];
13982                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13983                         continue;
13984
13985                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13986         }
13987 }
13988
13989 typedef struct r_decalsystem_splatqueue_s
13990 {
13991         vec3_t worldorigin;
13992         vec3_t worldnormal;
13993         float color[4];
13994         float tcrange[4];
13995         float worldsize;
13996         int decalsequence;
13997 }
13998 r_decalsystem_splatqueue_t;
13999
14000 int r_decalsystem_numqueued = 0;
14001 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
14002
14003 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)
14004 {
14005         r_decalsystem_splatqueue_t *queue;
14006
14007         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
14008                 return;
14009
14010         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
14011         VectorCopy(worldorigin, queue->worldorigin);
14012         VectorCopy(worldnormal, queue->worldnormal);
14013         Vector4Set(queue->color, r, g, b, a);
14014         Vector4Set(queue->tcrange, s1, t1, s2, t2);
14015         queue->worldsize = worldsize;
14016         queue->decalsequence = cl.decalsequence++;
14017 }
14018
14019 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
14020 {
14021         int i;
14022         r_decalsystem_splatqueue_t *queue;
14023
14024         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
14025                 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);
14026         r_decalsystem_numqueued = 0;
14027 }
14028
14029 extern cvar_t cl_decals_max;
14030 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
14031 {
14032         int i;
14033         decalsystem_t *decalsystem = &ent->decalsystem;
14034         int numdecals;
14035         int killsequence;
14036         tridecal_t *decal;
14037         float frametime;
14038         float lifetime;
14039
14040         if (!decalsystem->numdecals)
14041                 return;
14042
14043         if (r_showsurfaces.integer)
14044                 return;
14045
14046         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14047         {
14048                 R_DecalSystem_Reset(decalsystem);
14049                 return;
14050         }
14051
14052         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
14053         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
14054
14055         if (decalsystem->lastupdatetime)
14056                 frametime = (cl.time - decalsystem->lastupdatetime);
14057         else
14058                 frametime = 0;
14059         decalsystem->lastupdatetime = cl.time;
14060         decal = decalsystem->decals;
14061         numdecals = decalsystem->numdecals;
14062
14063         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14064         {
14065                 if (decal->color4ub[0][3])
14066                 {
14067                         decal->lived += frametime;
14068                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
14069                         {
14070                                 memset(decal, 0, sizeof(*decal));
14071                                 if (decalsystem->freedecal > i)
14072                                         decalsystem->freedecal = i;
14073                         }
14074                 }
14075         }
14076         decal = decalsystem->decals;
14077         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
14078                 numdecals--;
14079
14080         // collapse the array by shuffling the tail decals into the gaps
14081         for (;;)
14082         {
14083                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
14084                         decalsystem->freedecal++;
14085                 if (decalsystem->freedecal == numdecals)
14086                         break;
14087                 decal[decalsystem->freedecal] = decal[--numdecals];
14088         }
14089
14090         decalsystem->numdecals = numdecals;
14091
14092         if (numdecals <= 0)
14093         {
14094                 // if there are no decals left, reset decalsystem
14095                 R_DecalSystem_Reset(decalsystem);
14096         }
14097 }
14098
14099 extern skinframe_t *decalskinframe;
14100 static void R_DrawModelDecals_Entity(entity_render_t *ent)
14101 {
14102         int i;
14103         decalsystem_t *decalsystem = &ent->decalsystem;
14104         int numdecals;
14105         tridecal_t *decal;
14106         float faderate;
14107         float alpha;
14108         float *v3f;
14109         float *c4f;
14110         float *t2f;
14111         const int *e;
14112         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14113         int numtris = 0;
14114
14115         numdecals = decalsystem->numdecals;
14116         if (!numdecals)
14117                 return;
14118
14119         if (r_showsurfaces.integer)
14120                 return;
14121
14122         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14123         {
14124                 R_DecalSystem_Reset(decalsystem);
14125                 return;
14126         }
14127
14128         // if the model is static it doesn't matter what value we give for
14129         // wantnormals and wanttangents, so this logic uses only rules applicable
14130         // to a model, knowing that they are meaningless otherwise
14131         if (ent == r_refdef.scene.worldentity)
14132                 RSurf_ActiveWorldEntity();
14133         else
14134                 RSurf_ActiveModelEntity(ent, false, false, false);
14135
14136         decalsystem->lastupdatetime = cl.time;
14137         decal = decalsystem->decals;
14138
14139         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14140
14141         // update vertex positions for animated models
14142         v3f = decalsystem->vertex3f;
14143         c4f = decalsystem->color4f;
14144         t2f = decalsystem->texcoord2f;
14145         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14146         {
14147                 if (!decal->color4ub[0][3])
14148                         continue;
14149
14150                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14151                         continue;
14152
14153                 // update color values for fading decals
14154                 if (decal->lived >= cl_decals_time.value)
14155                 {
14156                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14157                         alpha *= (1.0f/255.0f);
14158                 }
14159                 else
14160                         alpha = 1.0f/255.0f;
14161
14162                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14163                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14164                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14165                 c4f[ 3] = 1;
14166                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14167                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14168                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14169                 c4f[ 7] = 1;
14170                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14171                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14172                 c4f[10] = decal->color4ub[2][2] * alpha;
14173                 c4f[11] = 1;
14174
14175                 t2f[0] = decal->texcoord2f[0][0];
14176                 t2f[1] = decal->texcoord2f[0][1];
14177                 t2f[2] = decal->texcoord2f[1][0];
14178                 t2f[3] = decal->texcoord2f[1][1];
14179                 t2f[4] = decal->texcoord2f[2][0];
14180                 t2f[5] = decal->texcoord2f[2][1];
14181
14182                 // update vertex positions for animated models
14183                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14184                 {
14185                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14186                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14187                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14188                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14189                 }
14190                 else
14191                 {
14192                         VectorCopy(decal->vertex3f[0], v3f);
14193                         VectorCopy(decal->vertex3f[1], v3f + 3);
14194                         VectorCopy(decal->vertex3f[2], v3f + 6);
14195                 }
14196
14197                 if (r_refdef.fogenabled)
14198                 {
14199                         alpha = RSurf_FogVertex(v3f);
14200                         VectorScale(c4f, alpha, c4f);
14201                         alpha = RSurf_FogVertex(v3f + 3);
14202                         VectorScale(c4f + 4, alpha, c4f + 4);
14203                         alpha = RSurf_FogVertex(v3f + 6);
14204                         VectorScale(c4f + 8, alpha, c4f + 8);
14205                 }
14206
14207                 v3f += 9;
14208                 c4f += 12;
14209                 t2f += 6;
14210                 numtris++;
14211         }
14212
14213         if (numtris > 0)
14214         {
14215                 r_refdef.stats.drawndecals += numtris;
14216
14217                 // now render the decals all at once
14218                 // (this assumes they all use one particle font texture!)
14219                 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);
14220 //              R_Mesh_ResetTextureState();
14221                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14222                 GL_DepthMask(false);
14223                 GL_DepthRange(0, 1);
14224                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14225                 GL_DepthTest(true);
14226                 GL_CullFace(GL_NONE);
14227                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14228                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14229                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14230         }
14231 }
14232
14233 static void R_DrawModelDecals(void)
14234 {
14235         int i, numdecals;
14236
14237         // fade faster when there are too many decals
14238         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14239         for (i = 0;i < r_refdef.scene.numentities;i++)
14240                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14241
14242         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14243         for (i = 0;i < r_refdef.scene.numentities;i++)
14244                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14245                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14246
14247         R_DecalSystem_ApplySplatEntitiesQueue();
14248
14249         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14250         for (i = 0;i < r_refdef.scene.numentities;i++)
14251                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14252
14253         r_refdef.stats.totaldecals += numdecals;
14254
14255         if (r_showsurfaces.integer)
14256                 return;
14257
14258         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14259
14260         for (i = 0;i < r_refdef.scene.numentities;i++)
14261         {
14262                 if (!r_refdef.viewcache.entityvisible[i])
14263                         continue;
14264                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14265                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14266         }
14267 }
14268
14269 extern cvar_t mod_collision_bih;
14270 void R_DrawDebugModel(void)
14271 {
14272         entity_render_t *ent = rsurface.entity;
14273         int i, j, k, l, flagsmask;
14274         const msurface_t *surface;
14275         dp_model_t *model = ent->model;
14276         vec3_t v;
14277
14278         switch(vid.renderpath)
14279         {
14280         case RENDERPATH_GL11:
14281         case RENDERPATH_GL13:
14282         case RENDERPATH_GL20:
14283         case RENDERPATH_CGGL:
14284                 break;
14285         case RENDERPATH_D3D9:
14286                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14287                 return;
14288         case RENDERPATH_D3D10:
14289                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14290                 return;
14291         case RENDERPATH_D3D11:
14292                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14293                 return;
14294         case RENDERPATH_SOFT:
14295                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14296                 return;
14297         }
14298
14299         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14300
14301 //      R_Mesh_ResetTextureState();
14302         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14303         GL_DepthRange(0, 1);
14304         GL_DepthTest(!r_showdisabledepthtest.integer);
14305         GL_DepthMask(false);
14306         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14307
14308         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14309         {
14310                 int triangleindex;
14311                 int bihleafindex;
14312                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14313                 const q3mbrush_t *brush;
14314                 const bih_t *bih = &model->collision_bih;
14315                 const bih_leaf_t *bihleaf;
14316                 float vertex3f[3][3];
14317                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14318                 cullbox = false;
14319                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14320                 {
14321                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14322                                 continue;
14323                         switch (bihleaf->type)
14324                         {
14325                         case BIH_BRUSH:
14326                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14327                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14328                                 {
14329                                         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);
14330                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14331                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14332                                 }
14333                                 break;
14334                         case BIH_COLLISIONTRIANGLE:
14335                                 triangleindex = bihleaf->itemindex;
14336                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14337                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14338                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14339                                 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);
14340                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14341                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14342                                 break;
14343                         case BIH_RENDERTRIANGLE:
14344                                 triangleindex = bihleaf->itemindex;
14345                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14346                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14347                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14348                                 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);
14349                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14350                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14351                                 break;
14352                         }
14353                 }
14354         }
14355
14356         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14357
14358         if (r_showtris.integer || (r_shownormals.value != 0))
14359         {
14360                 if (r_showdisabledepthtest.integer)
14361                 {
14362                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14363                         GL_DepthMask(false);
14364                 }
14365                 else
14366                 {
14367                         GL_BlendFunc(GL_ONE, GL_ZERO);
14368                         GL_DepthMask(true);
14369                 }
14370                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14371                 {
14372                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14373                                 continue;
14374                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14375                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14376                         {
14377                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14378                                 if (r_showtris.value > 0)
14379                                 {
14380                                         if (!rsurface.texture->currentlayers->depthmask)
14381                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14382                                         else if (ent == r_refdef.scene.worldentity)
14383                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14384                                         else
14385                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14386                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14387                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14388                                         RSurf_DrawBatch();
14389                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14390                                         CHECKGLERROR
14391                                 }
14392                                 if (r_shownormals.value < 0)
14393                                 {
14394                                         qglBegin(GL_LINES);
14395                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14396                                         {
14397                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14398                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14399                                                 qglVertex3f(v[0], v[1], v[2]);
14400                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14401                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14402                                                 qglVertex3f(v[0], v[1], v[2]);
14403                                         }
14404                                         qglEnd();
14405                                         CHECKGLERROR
14406                                 }
14407                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14408                                 {
14409                                         qglBegin(GL_LINES);
14410                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14411                                         {
14412                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14413                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14414                                                 qglVertex3f(v[0], v[1], v[2]);
14415                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14416                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14417                                                 qglVertex3f(v[0], v[1], v[2]);
14418                                         }
14419                                         qglEnd();
14420                                         CHECKGLERROR
14421                                         qglBegin(GL_LINES);
14422                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14423                                         {
14424                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14425                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14426                                                 qglVertex3f(v[0], v[1], v[2]);
14427                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14428                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14429                                                 qglVertex3f(v[0], v[1], v[2]);
14430                                         }
14431                                         qglEnd();
14432                                         CHECKGLERROR
14433                                         qglBegin(GL_LINES);
14434                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14435                                         {
14436                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14437                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14438                                                 qglVertex3f(v[0], v[1], v[2]);
14439                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14440                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14441                                                 qglVertex3f(v[0], v[1], v[2]);
14442                                         }
14443                                         qglEnd();
14444                                         CHECKGLERROR
14445                                 }
14446                         }
14447                 }
14448                 rsurface.texture = NULL;
14449         }
14450 }
14451
14452 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14453 int r_maxsurfacelist = 0;
14454 const msurface_t **r_surfacelist = NULL;
14455 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14456 {
14457         int i, j, endj, flagsmask;
14458         dp_model_t *model = r_refdef.scene.worldmodel;
14459         msurface_t *surfaces;
14460         unsigned char *update;
14461         int numsurfacelist = 0;
14462         if (model == NULL)
14463                 return;
14464
14465         if (r_maxsurfacelist < model->num_surfaces)
14466         {
14467                 r_maxsurfacelist = model->num_surfaces;
14468                 if (r_surfacelist)
14469                         Mem_Free((msurface_t**)r_surfacelist);
14470                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14471         }
14472
14473         RSurf_ActiveWorldEntity();
14474
14475         surfaces = model->data_surfaces;
14476         update = model->brushq1.lightmapupdateflags;
14477
14478         // update light styles on this submodel
14479         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14480         {
14481                 model_brush_lightstyleinfo_t *style;
14482                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14483                 {
14484                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14485                         {
14486                                 int *list = style->surfacelist;
14487                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14488                                 for (j = 0;j < style->numsurfaces;j++)
14489                                         update[list[j]] = true;
14490                         }
14491                 }
14492         }
14493
14494         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14495
14496         if (debug)
14497         {
14498                 R_DrawDebugModel();
14499                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14500                 return;
14501         }
14502
14503         rsurface.lightmaptexture = NULL;
14504         rsurface.deluxemaptexture = NULL;
14505         rsurface.uselightmaptexture = false;
14506         rsurface.texture = NULL;
14507         rsurface.rtlight = NULL;
14508         numsurfacelist = 0;
14509         // add visible surfaces to draw list
14510         for (i = 0;i < model->nummodelsurfaces;i++)
14511         {
14512                 j = model->sortedmodelsurfaces[i];
14513                 if (r_refdef.viewcache.world_surfacevisible[j])
14514                         r_surfacelist[numsurfacelist++] = surfaces + j;
14515         }
14516         // update lightmaps if needed
14517         if (model->brushq1.firstrender)
14518         {
14519                 model->brushq1.firstrender = false;
14520                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14521                         if (update[j])
14522                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14523         }
14524         else if (update)
14525         {
14526                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14527                         if (r_refdef.viewcache.world_surfacevisible[j])
14528                                 if (update[j])
14529                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14530         }
14531         // don't do anything if there were no surfaces
14532         if (!numsurfacelist)
14533         {
14534                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14535                 return;
14536         }
14537         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14538         GL_AlphaTest(false);
14539
14540         // add to stats if desired
14541         if (r_speeds.integer && !skysurfaces && !depthonly)
14542         {
14543                 r_refdef.stats.world_surfaces += numsurfacelist;
14544                 for (j = 0;j < numsurfacelist;j++)
14545                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14546         }
14547
14548         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14549 }
14550
14551 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14552 {
14553         int i, j, endj, flagsmask;
14554         dp_model_t *model = ent->model;
14555         msurface_t *surfaces;
14556         unsigned char *update;
14557         int numsurfacelist = 0;
14558         if (model == NULL)
14559                 return;
14560
14561         if (r_maxsurfacelist < model->num_surfaces)
14562         {
14563                 r_maxsurfacelist = model->num_surfaces;
14564                 if (r_surfacelist)
14565                         Mem_Free((msurface_t **)r_surfacelist);
14566                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14567         }
14568
14569         // if the model is static it doesn't matter what value we give for
14570         // wantnormals and wanttangents, so this logic uses only rules applicable
14571         // to a model, knowing that they are meaningless otherwise
14572         if (ent == r_refdef.scene.worldentity)
14573                 RSurf_ActiveWorldEntity();
14574         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14575                 RSurf_ActiveModelEntity(ent, false, false, false);
14576         else if (prepass)
14577                 RSurf_ActiveModelEntity(ent, true, true, true);
14578         else if (depthonly)
14579         {
14580                 switch (vid.renderpath)
14581                 {
14582                 case RENDERPATH_GL20:
14583                 case RENDERPATH_CGGL:
14584                 case RENDERPATH_D3D9:
14585                 case RENDERPATH_D3D10:
14586                 case RENDERPATH_D3D11:
14587                 case RENDERPATH_SOFT:
14588                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14589                         break;
14590                 case RENDERPATH_GL13:
14591                 case RENDERPATH_GL11:
14592                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14593                         break;
14594                 }
14595         }
14596         else
14597         {
14598                 switch (vid.renderpath)
14599                 {
14600                 case RENDERPATH_GL20:
14601                 case RENDERPATH_CGGL:
14602                 case RENDERPATH_D3D9:
14603                 case RENDERPATH_D3D10:
14604                 case RENDERPATH_D3D11:
14605                 case RENDERPATH_SOFT:
14606                         RSurf_ActiveModelEntity(ent, true, true, false);
14607                         break;
14608                 case RENDERPATH_GL13:
14609                 case RENDERPATH_GL11:
14610                         RSurf_ActiveModelEntity(ent, true, false, false);
14611                         break;
14612                 }
14613         }
14614
14615         surfaces = model->data_surfaces;
14616         update = model->brushq1.lightmapupdateflags;
14617
14618         // update light styles
14619         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14620         {
14621                 model_brush_lightstyleinfo_t *style;
14622                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14623                 {
14624                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14625                         {
14626                                 int *list = style->surfacelist;
14627                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14628                                 for (j = 0;j < style->numsurfaces;j++)
14629                                         update[list[j]] = true;
14630                         }
14631                 }
14632         }
14633
14634         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14635
14636         if (debug)
14637         {
14638                 R_DrawDebugModel();
14639                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14640                 return;
14641         }
14642
14643         rsurface.lightmaptexture = NULL;
14644         rsurface.deluxemaptexture = NULL;
14645         rsurface.uselightmaptexture = false;
14646         rsurface.texture = NULL;
14647         rsurface.rtlight = NULL;
14648         numsurfacelist = 0;
14649         // add visible surfaces to draw list
14650         for (i = 0;i < model->nummodelsurfaces;i++)
14651                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14652         // don't do anything if there were no surfaces
14653         if (!numsurfacelist)
14654         {
14655                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14656                 return;
14657         }
14658         // update lightmaps if needed
14659         if (update)
14660         {
14661                 int updated = 0;
14662                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14663                 {
14664                         if (update[j])
14665                         {
14666                                 updated++;
14667                                 R_BuildLightMap(ent, surfaces + j);
14668                         }
14669                 }
14670         }
14671         if (update)
14672                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14673                         if (update[j])
14674                                 R_BuildLightMap(ent, surfaces + j);
14675         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14676         GL_AlphaTest(false);
14677
14678         // add to stats if desired
14679         if (r_speeds.integer && !skysurfaces && !depthonly)
14680         {
14681                 r_refdef.stats.entities_surfaces += numsurfacelist;
14682                 for (j = 0;j < numsurfacelist;j++)
14683                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14684         }
14685
14686         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14687 }
14688
14689 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14690 {
14691         static texture_t texture;
14692         static msurface_t surface;
14693         const msurface_t *surfacelist = &surface;
14694
14695         // fake enough texture and surface state to render this geometry
14696
14697         texture.update_lastrenderframe = -1; // regenerate this texture
14698         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14699         texture.currentskinframe = skinframe;
14700         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14701         texture.offsetmapping = OFFSETMAPPING_OFF;
14702         texture.offsetscale = 1;
14703         texture.specularscalemod = 1;
14704         texture.specularpowermod = 1;
14705
14706         surface.texture = &texture;
14707         surface.num_triangles = numtriangles;
14708         surface.num_firsttriangle = firsttriangle;
14709         surface.num_vertices = numvertices;
14710         surface.num_firstvertex = firstvertex;
14711
14712         // now render it
14713         rsurface.texture = R_GetCurrentTexture(surface.texture);
14714         rsurface.lightmaptexture = NULL;
14715         rsurface.deluxemaptexture = NULL;
14716         rsurface.uselightmaptexture = false;
14717         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14718 }
14719
14720 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)
14721 {
14722         static msurface_t surface;
14723         const msurface_t *surfacelist = &surface;
14724
14725         // fake enough texture and surface state to render this geometry
14726         surface.texture = texture;
14727         surface.num_triangles = numtriangles;
14728         surface.num_firsttriangle = firsttriangle;
14729         surface.num_vertices = numvertices;
14730         surface.num_firstvertex = firstvertex;
14731
14732         // now render it
14733         rsurface.texture = R_GetCurrentTexture(surface.texture);
14734         rsurface.lightmaptexture = NULL;
14735         rsurface.deluxemaptexture = NULL;
14736         rsurface.uselightmaptexture = false;
14737         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14738 }