]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix a typo in the cg shader setup
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 #ifdef SUPPORTD3D
32 #include <d3d9.h>
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
34 #endif
35
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
38
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
40
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
43 qboolean r_loadfog;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
46
47 //
48 // screen size info
49 //
50 r_refdef_t r_refdef;
51
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
60
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
66
67 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
73 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
80 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
81 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
90 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95
96 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
97 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
98 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
99
100 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
101 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
102 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
103 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
104 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
105 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
106 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
107 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
108 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
109 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
110 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
111 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
112 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
113 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
115 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
117 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
118 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
119
120 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
121 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
122 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
123 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
124 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
125 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
126 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
127 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
128
129 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
130 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
131
132 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
133 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
137
138 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
139 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
140 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
141
142 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
143 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
144 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
145 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
146 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
147 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
148 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155
156 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
157 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
158 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
159 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
160 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
161 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
162
163 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
164 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
165 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
166 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
167
168 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
169 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
170 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
171 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
172 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
173 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
174 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
175
176 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
177 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
178 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
179 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
180
181 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
182
183 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
184
185 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
186
187 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
188 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
189 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
190 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
191 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
192 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
193 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
194 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
195 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
196
197 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
198 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
199
200 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
201
202 extern cvar_t v_glslgamma;
203
204 extern qboolean v_flipped_state;
205
206 static struct r_bloomstate_s
207 {
208         qboolean enabled;
209         qboolean hdr;
210
211         int bloomwidth, bloomheight;
212
213         int screentexturewidth, screentextureheight;
214         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
215
216         int bloomtexturewidth, bloomtextureheight;
217         rtexture_t *texture_bloom;
218
219         // arrays for rendering the screen passes
220         float screentexcoord2f[8];
221         float bloomtexcoord2f[8];
222         float offsettexcoord2f[8];
223
224         r_viewport_t viewport;
225 }
226 r_bloomstate;
227
228 r_waterstate_t r_waterstate;
229
230 /// shadow volume bsp struct with automatically growing nodes buffer
231 svbsp_t r_svbsp;
232
233 rtexture_t *r_texture_blanknormalmap;
234 rtexture_t *r_texture_white;
235 rtexture_t *r_texture_grey128;
236 rtexture_t *r_texture_black;
237 rtexture_t *r_texture_notexture;
238 rtexture_t *r_texture_whitecube;
239 rtexture_t *r_texture_normalizationcube;
240 rtexture_t *r_texture_fogattenuation;
241 rtexture_t *r_texture_fogheighttexture;
242 rtexture_t *r_texture_gammaramps;
243 unsigned int r_texture_gammaramps_serial;
244 //rtexture_t *r_texture_fogintensity;
245 rtexture_t *r_texture_reflectcube;
246
247 // TODO: hash lookups?
248 typedef struct cubemapinfo_s
249 {
250         char basename[64];
251         rtexture_t *texture;
252 }
253 cubemapinfo_t;
254
255 int r_texture_numcubemaps;
256 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
257
258 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
259 unsigned int r_numqueries;
260 unsigned int r_maxqueries;
261
262 typedef struct r_qwskincache_s
263 {
264         char name[MAX_QPATH];
265         skinframe_t *skinframe;
266 }
267 r_qwskincache_t;
268
269 static r_qwskincache_t *r_qwskincache;
270 static int r_qwskincache_size;
271
272 /// vertex coordinates for a quad that covers the screen exactly
273 extern const float r_screenvertex3f[12];
274 extern const float r_d3dscreenvertex3f[12];
275 const float r_screenvertex3f[12] =
276 {
277         0, 0, 0,
278         1, 0, 0,
279         1, 1, 0,
280         0, 1, 0
281 };
282 const float r_d3dscreenvertex3f[12] =
283 {
284         0, 1, 0,
285         1, 1, 0,
286         1, 0, 0,
287         0, 0, 0
288 };
289
290 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
291 {
292         int i;
293         for (i = 0;i < verts;i++)
294         {
295                 out[0] = in[0] * r;
296                 out[1] = in[1] * g;
297                 out[2] = in[2] * b;
298                 out[3] = in[3];
299                 in += 4;
300                 out += 4;
301         }
302 }
303
304 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
305 {
306         int i;
307         for (i = 0;i < verts;i++)
308         {
309                 out[0] = r;
310                 out[1] = g;
311                 out[2] = b;
312                 out[3] = a;
313                 out += 4;
314         }
315 }
316
317 // FIXME: move this to client?
318 void FOG_clear(void)
319 {
320         if (gamemode == GAME_NEHAHRA)
321         {
322                 Cvar_Set("gl_fogenable", "0");
323                 Cvar_Set("gl_fogdensity", "0.2");
324                 Cvar_Set("gl_fogred", "0.3");
325                 Cvar_Set("gl_foggreen", "0.3");
326                 Cvar_Set("gl_fogblue", "0.3");
327         }
328         r_refdef.fog_density = 0;
329         r_refdef.fog_red = 0;
330         r_refdef.fog_green = 0;
331         r_refdef.fog_blue = 0;
332         r_refdef.fog_alpha = 1;
333         r_refdef.fog_start = 0;
334         r_refdef.fog_end = 16384;
335         r_refdef.fog_height = 1<<30;
336         r_refdef.fog_fadedepth = 128;
337         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
338 }
339
340 static void R_BuildBlankTextures(void)
341 {
342         unsigned char data[4];
343         data[2] = 128; // normal X
344         data[1] = 128; // normal Y
345         data[0] = 255; // normal Z
346         data[3] = 128; // height
347         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
348         data[0] = 255;
349         data[1] = 255;
350         data[2] = 255;
351         data[3] = 255;
352         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
353         data[0] = 128;
354         data[1] = 128;
355         data[2] = 128;
356         data[3] = 255;
357         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358         data[0] = 0;
359         data[1] = 0;
360         data[2] = 0;
361         data[3] = 255;
362         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363 }
364
365 static void R_BuildNoTexture(void)
366 {
367         int x, y;
368         unsigned char pix[16][16][4];
369         // this makes a light grey/dark grey checkerboard texture
370         for (y = 0;y < 16;y++)
371         {
372                 for (x = 0;x < 16;x++)
373                 {
374                         if ((y < 8) ^ (x < 8))
375                         {
376                                 pix[y][x][0] = 128;
377                                 pix[y][x][1] = 128;
378                                 pix[y][x][2] = 128;
379                                 pix[y][x][3] = 255;
380                         }
381                         else
382                         {
383                                 pix[y][x][0] = 64;
384                                 pix[y][x][1] = 64;
385                                 pix[y][x][2] = 64;
386                                 pix[y][x][3] = 255;
387                         }
388                 }
389         }
390         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildWhiteCube(void)
394 {
395         unsigned char data[6*1*1*4];
396         memset(data, 255, sizeof(data));
397         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
398 }
399
400 static void R_BuildNormalizationCube(void)
401 {
402         int x, y, side;
403         vec3_t v;
404         vec_t s, t, intensity;
405 #define NORMSIZE 64
406         unsigned char *data;
407         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
408         for (side = 0;side < 6;side++)
409         {
410                 for (y = 0;y < NORMSIZE;y++)
411                 {
412                         for (x = 0;x < NORMSIZE;x++)
413                         {
414                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
415                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
416                                 switch(side)
417                                 {
418                                 default:
419                                 case 0:
420                                         v[0] = 1;
421                                         v[1] = -t;
422                                         v[2] = -s;
423                                         break;
424                                 case 1:
425                                         v[0] = -1;
426                                         v[1] = -t;
427                                         v[2] = s;
428                                         break;
429                                 case 2:
430                                         v[0] = s;
431                                         v[1] = 1;
432                                         v[2] = t;
433                                         break;
434                                 case 3:
435                                         v[0] = s;
436                                         v[1] = -1;
437                                         v[2] = -t;
438                                         break;
439                                 case 4:
440                                         v[0] = s;
441                                         v[1] = -t;
442                                         v[2] = 1;
443                                         break;
444                                 case 5:
445                                         v[0] = -s;
446                                         v[1] = -t;
447                                         v[2] = -1;
448                                         break;
449                                 }
450                                 intensity = 127.0f / sqrt(DotProduct(v, v));
451                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
452                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
453                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
454                                 data[((side*64+y)*64+x)*4+3] = 255;
455                         }
456                 }
457         }
458         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
459         Mem_Free(data);
460 }
461
462 static void R_BuildFogTexture(void)
463 {
464         int x, b;
465 #define FOGWIDTH 256
466         unsigned char data1[FOGWIDTH][4];
467         //unsigned char data2[FOGWIDTH][4];
468         double d, r, alpha;
469
470         r_refdef.fogmasktable_start = r_refdef.fog_start;
471         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
472         r_refdef.fogmasktable_range = r_refdef.fogrange;
473         r_refdef.fogmasktable_density = r_refdef.fog_density;
474
475         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
476         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
477         {
478                 d = (x * r - r_refdef.fogmasktable_start);
479                 if(developer_extra.integer)
480                         Con_DPrintf("%f ", d);
481                 d = max(0, d);
482                 if (r_fog_exp2.integer)
483                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
484                 else
485                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
486                 if(developer_extra.integer)
487                         Con_DPrintf(" : %f ", alpha);
488                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
489                 if(developer_extra.integer)
490                         Con_DPrintf(" = %f\n", alpha);
491                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
492         }
493
494         for (x = 0;x < FOGWIDTH;x++)
495         {
496                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
497                 data1[x][0] = b;
498                 data1[x][1] = b;
499                 data1[x][2] = b;
500                 data1[x][3] = 255;
501                 //data2[x][0] = 255 - b;
502                 //data2[x][1] = 255 - b;
503                 //data2[x][2] = 255 - b;
504                 //data2[x][3] = 255;
505         }
506         if (r_texture_fogattenuation)
507         {
508                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
509                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
510         }
511         else
512         {
513                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
514                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
515         }
516 }
517
518 static void R_BuildFogHeightTexture(void)
519 {
520         unsigned char *inpixels;
521         int size;
522         int x;
523         int y;
524         int j;
525         float c[4];
526         float f;
527         inpixels = NULL;
528         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
529         if (r_refdef.fogheighttexturename[0])
530                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
531         if (!inpixels)
532         {
533                 r_refdef.fog_height_tablesize = 0;
534                 if (r_texture_fogheighttexture)
535                         R_FreeTexture(r_texture_fogheighttexture);
536                 r_texture_fogheighttexture = NULL;
537                 if (r_refdef.fog_height_table2d)
538                         Mem_Free(r_refdef.fog_height_table2d);
539                 r_refdef.fog_height_table2d = NULL;
540                 if (r_refdef.fog_height_table1d)
541                         Mem_Free(r_refdef.fog_height_table1d);
542                 r_refdef.fog_height_table1d = NULL;
543                 return;
544         }
545         size = image_width;
546         r_refdef.fog_height_tablesize = size;
547         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
548         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
549         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
550         Mem_Free(inpixels);
551         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
552         // average fog color table accounting for every fog layer between a point
553         // and the camera.  (Note: attenuation is handled separately!)
554         for (y = 0;y < size;y++)
555         {
556                 for (x = 0;x < size;x++)
557                 {
558                         Vector4Clear(c);
559                         f = 0;
560                         if (x < y)
561                         {
562                                 for (j = x;j <= y;j++)
563                                 {
564                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
565                                         f++;
566                                 }
567                         }
568                         else
569                         {
570                                 for (j = x;j >= y;j--)
571                                 {
572                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
573                                         f++;
574                                 }
575                         }
576                         f = 1.0f / f;
577                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
578                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
579                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
580                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
581                 }
582         }
583         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
584 }
585
586 //=======================================================================================================================================================
587
588 static const char *builtinshaderstring =
589 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
590 "// written by Forest 'LordHavoc' Hale\n"
591 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
592 "\n"
593 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
594 "# define USEFOG\n"
595 "#endif\n"
596 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
597 "#define USELIGHTMAP\n"
598 "#endif\n"
599 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
600 "#define USEEYEVECTOR\n"
601 "#endif\n"
602 "\n"
603 "#ifdef USESHADOWMAP2D\n"
604 "# ifdef GL_EXT_gpu_shader4\n"
605 "#   extension GL_EXT_gpu_shader4 : enable\n"
606 "# endif\n"
607 "# ifdef GL_ARB_texture_gather\n"
608 "#   extension GL_ARB_texture_gather : enable\n"
609 "# else\n"
610 "#   ifdef GL_AMD_texture_texture4\n"
611 "#     extension GL_AMD_texture_texture4 : enable\n"
612 "#   endif\n"
613 "# endif\n"
614 "#endif\n"
615 "\n"
616 "//#ifdef USESHADOWSAMPLER\n"
617 "//# extension GL_ARB_shadow : enable\n"
618 "//#endif\n"
619 "\n"
620 "//#ifdef __GLSL_CG_DATA_TYPES\n"
621 "//# define myhalf half\n"
622 "//# define myhalf2 half2\n"
623 "//# define myhalf3 half3\n"
624 "//# define myhalf4 half4\n"
625 "//#else\n"
626 "# define myhalf float\n"
627 "# define myhalf2 vec2\n"
628 "# define myhalf3 vec3\n"
629 "# define myhalf4 vec4\n"
630 "//#endif\n"
631 "\n"
632 "#ifdef VERTEX_SHADER\n"
633 "uniform mat4 ModelViewProjectionMatrix;\n"
634 "#endif\n"
635 "\n"
636 "#ifdef MODE_DEPTH_OR_SHADOW\n"
637 "#ifdef VERTEX_SHADER\n"
638 "void main(void)\n"
639 "{\n"
640 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
641 "}\n"
642 "#endif\n"
643 "#else // !MODE_DEPTH_ORSHADOW\n"
644 "\n"
645 "\n"
646 "\n"
647 "\n"
648 "#ifdef MODE_SHOWDEPTH\n"
649 "#ifdef VERTEX_SHADER\n"
650 "void main(void)\n"
651 "{\n"
652 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
653 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
654 "}\n"
655 "#endif\n"
656 "\n"
657 "#ifdef FRAGMENT_SHADER\n"
658 "void main(void)\n"
659 "{\n"
660 "       gl_FragColor = gl_Color;\n"
661 "}\n"
662 "#endif\n"
663 "#else // !MODE_SHOWDEPTH\n"
664 "\n"
665 "\n"
666 "\n"
667 "\n"
668 "#ifdef MODE_POSTPROCESS\n"
669 "varying vec2 TexCoord1;\n"
670 "varying vec2 TexCoord2;\n"
671 "\n"
672 "#ifdef VERTEX_SHADER\n"
673 "void main(void)\n"
674 "{\n"
675 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
676 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
677 "#ifdef USEBLOOM\n"
678 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
679 "#endif\n"
680 "}\n"
681 "#endif\n"
682 "\n"
683 "#ifdef FRAGMENT_SHADER\n"
684 "uniform sampler2D Texture_First;\n"
685 "#ifdef USEBLOOM\n"
686 "uniform sampler2D Texture_Second;\n"
687 "uniform vec4 BloomColorSubtract;\n"
688 "#endif\n"
689 "#ifdef USEGAMMARAMPS\n"
690 "uniform sampler2D Texture_GammaRamps;\n"
691 "#endif\n"
692 "#ifdef USESATURATION\n"
693 "uniform float Saturation;\n"
694 "#endif\n"
695 "#ifdef USEVIEWTINT\n"
696 "uniform vec4 ViewTintColor;\n"
697 "#endif\n"
698 "//uncomment these if you want to use them:\n"
699 "uniform vec4 UserVec1;\n"
700 "uniform vec4 UserVec2;\n"
701 "// uniform vec4 UserVec3;\n"
702 "// uniform vec4 UserVec4;\n"
703 "// uniform float ClientTime;\n"
704 "uniform vec2 PixelSize;\n"
705 "void main(void)\n"
706 "{\n"
707 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
708 "#ifdef USEBLOOM\n"
709 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
710 "#endif\n"
711 "#ifdef USEVIEWTINT\n"
712 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
713 "#endif\n"
714 "\n"
715 "#ifdef USEPOSTPROCESSING\n"
716 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
717 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
718 "       float sobel = 1.0;\n"
719 "       // vec2 ts = textureSize(Texture_First, 0);\n"
720 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
721 "       vec2 px = PixelSize;\n"
722 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
723 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
724 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
725 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
726 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
727 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
728 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
729 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
730 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
731 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
732 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
733 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
734 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
735 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
736 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
737 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
738 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
739 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
740 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
741 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
742 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
743 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
744 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
745 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
746 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
747 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
748 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
749 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
750 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
751 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
752 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
753 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
754 "#endif\n"
755 "\n"
756 "#ifdef USESATURATION\n"
757 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
758 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
759 "       // 'vampire sight' effect, wheres red is compensated\n"
760 "       #ifdef SATURATION_REDCOMPENSATE\n"
761 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
762 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
763 "               gl_FragColor.r += rboost;\n"
764 "       #else\n"
765 "               // normal desaturation\n"
766 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
767 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
768 "       #endif\n"
769 "#endif\n"
770 "\n"
771 "#ifdef USEGAMMARAMPS\n"
772 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
773 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
774 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
775 "#endif\n"
776 "}\n"
777 "#endif\n"
778 "#else // !MODE_POSTPROCESS\n"
779 "\n"
780 "\n"
781 "\n"
782 "\n"
783 "#ifdef MODE_GENERIC\n"
784 "#ifdef USEDIFFUSE\n"
785 "varying vec2 TexCoord1;\n"
786 "#endif\n"
787 "#ifdef USESPECULAR\n"
788 "varying vec2 TexCoord2;\n"
789 "#endif\n"
790 "#ifdef VERTEX_SHADER\n"
791 "void main(void)\n"
792 "{\n"
793 "       gl_FrontColor = gl_Color;\n"
794 "#ifdef USEDIFFUSE\n"
795 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
796 "#endif\n"
797 "#ifdef USESPECULAR\n"
798 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
799 "#endif\n"
800 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
801 "}\n"
802 "#endif\n"
803 "\n"
804 "#ifdef FRAGMENT_SHADER\n"
805 "#ifdef USEDIFFUSE\n"
806 "uniform sampler2D Texture_First;\n"
807 "#endif\n"
808 "#ifdef USESPECULAR\n"
809 "uniform sampler2D Texture_Second;\n"
810 "#endif\n"
811 "\n"
812 "void main(void)\n"
813 "{\n"
814 "#ifdef USEVIEWTINT\n"
815 "       gl_FragColor = gl_Color;\n"
816 "#else\n"
817 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
818 "#endif\n"
819 "#ifdef USEDIFFUSE\n"
820 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
821 "#endif\n"
822 "\n"
823 "#ifdef USESPECULAR\n"
824 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
825 "# ifdef USECOLORMAPPING\n"
826 "       gl_FragColor *= tex2;\n"
827 "# endif\n"
828 "# ifdef USEGLOW\n"
829 "       gl_FragColor += tex2;\n"
830 "# endif\n"
831 "# ifdef USEVERTEXTEXTUREBLEND\n"
832 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
833 "# endif\n"
834 "#endif\n"
835 "}\n"
836 "#endif\n"
837 "#else // !MODE_GENERIC\n"
838 "\n"
839 "\n"
840 "\n"
841 "\n"
842 "#ifdef MODE_BLOOMBLUR\n"
843 "varying TexCoord;\n"
844 "#ifdef VERTEX_SHADER\n"
845 "void main(void)\n"
846 "{\n"
847 "       gl_FrontColor = gl_Color;\n"
848 "       TexCoord = gl_MultiTexCoord0.xy;\n"
849 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
850 "}\n"
851 "#endif\n"
852 "\n"
853 "#ifdef FRAGMENT_SHADER\n"
854 "uniform sampler2D Texture_First;\n"
855 "uniform vec4 BloomBlur_Parameters;\n"
856 "\n"
857 "void main(void)\n"
858 "{\n"
859 "       int i;\n"
860 "       vec2 tc = TexCoord;\n"
861 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
862 "       tc += BloomBlur_Parameters.xy;\n"
863 "       for (i = 1;i < SAMPLES;i++)\n"
864 "       {\n"
865 "               color += texture2D(Texture_First, tc).rgb;\n"
866 "               tc += BloomBlur_Parameters.xy;\n"
867 "       }\n"
868 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
869 "}\n"
870 "#endif\n"
871 "#else // !MODE_BLOOMBLUR\n"
872 "#ifdef MODE_REFRACTION\n"
873 "varying vec2 TexCoord;\n"
874 "varying vec4 ModelViewProjectionPosition;\n"
875 "uniform mat4 TexMatrix;\n"
876 "#ifdef VERTEX_SHADER\n"
877 "\n"
878 "void main(void)\n"
879 "{\n"
880 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
881 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
882 "       ModelViewProjectionPosition = gl_Position;\n"
883 "}\n"
884 "#endif\n"
885 "\n"
886 "#ifdef FRAGMENT_SHADER\n"
887 "uniform sampler2D Texture_Normal;\n"
888 "uniform sampler2D Texture_Refraction;\n"
889 "uniform sampler2D Texture_Reflection;\n"
890 "\n"
891 "uniform vec4 DistortScaleRefractReflect;\n"
892 "uniform vec4 ScreenScaleRefractReflect;\n"
893 "uniform vec4 ScreenCenterRefractReflect;\n"
894 "uniform vec4 RefractColor;\n"
895 "uniform vec4 ReflectColor;\n"
896 "uniform float ReflectFactor;\n"
897 "uniform float ReflectOffset;\n"
898 "\n"
899 "void main(void)\n"
900 "{\n"
901 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
902 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
903 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
904 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
905 "       // FIXME temporary hack to detect the case that the reflection\n"
906 "       // gets blackened at edges due to leaving the area that contains actual\n"
907 "       // content.\n"
908 "       // Remove this 'ack once we have a better way to stop this thing from\n"
909 "       // 'appening.\n"
910 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
911 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
912 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
913 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
914 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
915 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
916 "}\n"
917 "#endif\n"
918 "#else // !MODE_REFRACTION\n"
919 "\n"
920 "\n"
921 "\n"
922 "\n"
923 "#ifdef MODE_WATER\n"
924 "varying vec2 TexCoord;\n"
925 "varying vec3 EyeVector;\n"
926 "varying vec4 ModelViewProjectionPosition;\n"
927 "#ifdef VERTEX_SHADER\n"
928 "uniform vec3 EyePosition;\n"
929 "uniform mat4 TexMatrix;\n"
930 "\n"
931 "void main(void)\n"
932 "{\n"
933 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
934 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
935 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
936 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
937 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
938 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
939 "       ModelViewProjectionPosition = gl_Position;\n"
940 "}\n"
941 "#endif\n"
942 "\n"
943 "#ifdef FRAGMENT_SHADER\n"
944 "uniform sampler2D Texture_Normal;\n"
945 "uniform sampler2D Texture_Refraction;\n"
946 "uniform sampler2D Texture_Reflection;\n"
947 "\n"
948 "uniform vec4 DistortScaleRefractReflect;\n"
949 "uniform vec4 ScreenScaleRefractReflect;\n"
950 "uniform vec4 ScreenCenterRefractReflect;\n"
951 "uniform vec4 RefractColor;\n"
952 "uniform vec4 ReflectColor;\n"
953 "uniform float ReflectFactor;\n"
954 "uniform float ReflectOffset;\n"
955 "uniform float ClientTime;\n"
956 "#ifdef USENORMALMAPSCROLLBLEND\n"
957 "uniform vec2 NormalmapScrollBlend;\n"
958 "#endif\n"
959 "\n"
960 "void main(void)\n"
961 "{\n"
962 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
963 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
964 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
965 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
966 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
967 "       #ifdef USENORMALMAPSCROLLBLEND\n"
968 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
969 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
970 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
971 "       #else\n"
972 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
973 "       #endif\n"
974 "       // FIXME temporary hack to detect the case that the reflection\n"
975 "       // gets blackened at edges due to leaving the area that contains actual\n"
976 "       // content.\n"
977 "       // Remove this 'ack once we have a better way to stop this thing from\n"
978 "       // 'appening.\n"
979 "       float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
980 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
981 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
982 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
983 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
984 "       f  = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
985 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
986 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
987 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
988 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
989 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
990 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
991 "}\n"
992 "#endif\n"
993 "#else // !MODE_WATER\n"
994 "\n"
995 "\n"
996 "\n"
997 "\n"
998 "// common definitions between vertex shader and fragment shader:\n"
999 "\n"
1000 "varying vec2 TexCoord;\n"
1001 "#ifdef USEVERTEXTEXTUREBLEND\n"
1002 "varying vec2 TexCoord2;\n"
1003 "#endif\n"
1004 "#ifdef USELIGHTMAP\n"
1005 "varying vec2 TexCoordLightmap;\n"
1006 "#endif\n"
1007 "\n"
1008 "#ifdef MODE_LIGHTSOURCE\n"
1009 "varying vec3 CubeVector;\n"
1010 "#endif\n"
1011 "\n"
1012 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1013 "varying vec3 LightVector;\n"
1014 "#endif\n"
1015 "\n"
1016 "#ifdef USEEYEVECTOR\n"
1017 "varying vec3 EyeVector;\n"
1018 "#endif\n"
1019 "#ifdef USEFOG\n"
1020 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1021 "#endif\n"
1022 "\n"
1023 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1024 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1025 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1026 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1027 "#endif\n"
1028 "\n"
1029 "#ifdef USEREFLECTION\n"
1030 "varying vec4 ModelViewProjectionPosition;\n"
1031 "#endif\n"
1032 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1033 "uniform vec3 LightPosition;\n"
1034 "varying vec4 ModelViewPosition;\n"
1035 "#endif\n"
1036 "\n"
1037 "#ifdef MODE_LIGHTSOURCE\n"
1038 "uniform vec3 LightPosition;\n"
1039 "#endif\n"
1040 "uniform vec3 EyePosition;\n"
1041 "#ifdef MODE_LIGHTDIRECTION\n"
1042 "uniform vec3 LightDir;\n"
1043 "#endif\n"
1044 "uniform vec4 FogPlane;\n"
1045 "\n"
1046 "#ifdef USESHADOWMAPORTHO\n"
1047 "varying vec3 ShadowMapTC;\n"
1048 "#endif\n"
1049 "\n"
1050 "\n"
1051 "\n"
1052 "\n"
1053 "\n"
1054 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1055 "\n"
1056 "// fragment shader specific:\n"
1057 "#ifdef FRAGMENT_SHADER\n"
1058 "\n"
1059 "uniform sampler2D Texture_Normal;\n"
1060 "uniform sampler2D Texture_Color;\n"
1061 "uniform sampler2D Texture_Gloss;\n"
1062 "#ifdef USEGLOW\n"
1063 "uniform sampler2D Texture_Glow;\n"
1064 "#endif\n"
1065 "#ifdef USEVERTEXTEXTUREBLEND\n"
1066 "uniform sampler2D Texture_SecondaryNormal;\n"
1067 "uniform sampler2D Texture_SecondaryColor;\n"
1068 "uniform sampler2D Texture_SecondaryGloss;\n"
1069 "#ifdef USEGLOW\n"
1070 "uniform sampler2D Texture_SecondaryGlow;\n"
1071 "#endif\n"
1072 "#endif\n"
1073 "#ifdef USECOLORMAPPING\n"
1074 "uniform sampler2D Texture_Pants;\n"
1075 "uniform sampler2D Texture_Shirt;\n"
1076 "#endif\n"
1077 "#ifdef USEFOG\n"
1078 "#ifdef USEFOGHEIGHTTEXTURE\n"
1079 "uniform sampler2D Texture_FogHeightTexture;\n"
1080 "#endif\n"
1081 "uniform sampler2D Texture_FogMask;\n"
1082 "#endif\n"
1083 "#ifdef USELIGHTMAP\n"
1084 "uniform sampler2D Texture_Lightmap;\n"
1085 "#endif\n"
1086 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1087 "uniform sampler2D Texture_Deluxemap;\n"
1088 "#endif\n"
1089 "#ifdef USEREFLECTION\n"
1090 "uniform sampler2D Texture_Reflection;\n"
1091 "#endif\n"
1092 "\n"
1093 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1094 "uniform sampler2D Texture_ScreenDepth;\n"
1095 "uniform sampler2D Texture_ScreenNormalMap;\n"
1096 "#endif\n"
1097 "#ifdef USEDEFERREDLIGHTMAP\n"
1098 "uniform sampler2D Texture_ScreenDiffuse;\n"
1099 "uniform sampler2D Texture_ScreenSpecular;\n"
1100 "#endif\n"
1101 "\n"
1102 "uniform myhalf3 Color_Pants;\n"
1103 "uniform myhalf3 Color_Shirt;\n"
1104 "uniform myhalf3 FogColor;\n"
1105 "\n"
1106 "#ifdef USEFOG\n"
1107 "uniform float FogRangeRecip;\n"
1108 "uniform float FogPlaneViewDist;\n"
1109 "uniform float FogHeightFade;\n"
1110 "vec3 FogVertex(vec3 surfacecolor)\n"
1111 "{\n"
1112 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1113 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1114 "       float fogfrac;\n"
1115 "#ifdef USEFOGHEIGHTTEXTURE\n"
1116 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1117 "       fogfrac = fogheightpixel.a;\n"
1118 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1119 "#else\n"
1120 "# ifdef USEFOGOUTSIDE\n"
1121 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1122 "# else\n"
1123 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1124 "# endif\n"
1125 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1126 "#endif\n"
1127 "}\n"
1128 "#endif\n"
1129 "\n"
1130 "#ifdef USEOFFSETMAPPING\n"
1131 "uniform float OffsetMapping_Scale;\n"
1132 "vec2 OffsetMapping(vec2 TexCoord)\n"
1133 "{\n"
1134 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1135 "       // 14 sample relief mapping: linear search and then binary search\n"
1136 "       // this basically steps forward a small amount repeatedly until it finds\n"
1137 "       // itself inside solid, then jitters forward and back using decreasing\n"
1138 "       // amounts to find the impact\n"
1139 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1140 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1141 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1142 "       vec3 RT = vec3(TexCoord, 1);\n"
1143 "       OffsetVector *= 0.1;\n"
1144 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1145 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1146 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1147 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1148 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1149 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1150 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1151 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1152 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1153 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1154 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1155 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1156 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1157 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1158 "       return RT.xy;\n"
1159 "#else\n"
1160 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1161 "       // this basically moves forward the full distance, and then backs up based\n"
1162 "       // on height of samples\n"
1163 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1164 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1165 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1166 "       TexCoord += OffsetVector;\n"
1167 "       OffsetVector *= 0.5;\n"
1168 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1169 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1170 "       return TexCoord;\n"
1171 "#endif\n"
1172 "}\n"
1173 "#endif // USEOFFSETMAPPING\n"
1174 "\n"
1175 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1176 "uniform sampler2D Texture_Attenuation;\n"
1177 "uniform samplerCube Texture_Cube;\n"
1178 "#endif\n"
1179 "\n"
1180 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1181 "\n"
1182 "#ifdef USESHADOWMAP2D\n"
1183 "# ifdef USESHADOWSAMPLER\n"
1184 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1185 "# else\n"
1186 "uniform sampler2D Texture_ShadowMap2D;\n"
1187 "# endif\n"
1188 "#endif\n"
1189 "\n"
1190 "#ifdef USESHADOWMAPVSDCT\n"
1191 "uniform samplerCube Texture_CubeProjection;\n"
1192 "#endif\n"
1193 "\n"
1194 "#if defined(USESHADOWMAP2D)\n"
1195 "uniform vec2 ShadowMap_TextureScale;\n"
1196 "uniform vec4 ShadowMap_Parameters;\n"
1197 "#endif\n"
1198 "\n"
1199 "#if defined(USESHADOWMAP2D)\n"
1200 "# ifdef USESHADOWMAPORTHO\n"
1201 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1202 "# else\n"
1203 "#  ifdef USESHADOWMAPVSDCT\n"
1204 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1205 "{\n"
1206 "       vec3 adir = abs(dir);\n"
1207 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1208 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1209 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1210 "}\n"
1211 "#  else\n"
1212 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1213 "{\n"
1214 "       vec3 adir = abs(dir);\n"
1215 "       float ma = adir.z;\n"
1216 "       vec4 proj = vec4(dir, 2.5);\n"
1217 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1218 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1219 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1220 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1221 "}\n"
1222 "#  endif\n"
1223 "# endif\n"
1224 "#endif // defined(USESHADOWMAP2D)\n"
1225 "\n"
1226 "# ifdef USESHADOWMAP2D\n"
1227 "float ShadowMapCompare(vec3 dir)\n"
1228 "{\n"
1229 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1230 "       float f;\n"
1231 "\n"
1232 "#  ifdef USESHADOWSAMPLER\n"
1233 "#    ifdef USESHADOWMAPPCF\n"
1234 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1235 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1236 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1237 "#    else\n"
1238 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1239 "#    endif\n"
1240 "#  else\n"
1241 "#    ifdef USESHADOWMAPPCF\n"
1242 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1243 "#      ifdef GL_ARB_texture_gather\n"
1244 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1245 "#      else\n"
1246 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1247 "#      endif\n"
1248 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1249 "#      if USESHADOWMAPPCF > 1\n"
1250 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1251 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1252 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1253 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1254 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1255 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1256 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1257 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1258 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1259 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1260 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1261 "       locols.yz += group2.ab;\n"
1262 "       hicols.yz += group8.rg;\n"
1263 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1264 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1265 "                               mix(locols, hicols, offset.y);\n"
1266 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1267 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1268 "       f = dot(cols, vec4(1.0/25.0));\n"
1269 "#      else\n"
1270 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1271 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1272 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1273 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1274 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1275 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1276 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1277 "#      endif\n"
1278 "#     else\n"
1279 "#      ifdef GL_EXT_gpu_shader4\n"
1280 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1281 "#      else\n"
1282 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1283 "#      endif\n"
1284 "#      if USESHADOWMAPPCF > 1\n"
1285 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1286 "       center *= ShadowMap_TextureScale;\n"
1287 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1288 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1289 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1290 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1291 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1292 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1293 "#      else\n"
1294 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1295 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1296 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1297 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1298 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1299 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1300 "#      endif\n"
1301 "#     endif\n"
1302 "#    else\n"
1303 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1304 "#    endif\n"
1305 "#  endif\n"
1306 "#  ifdef USESHADOWMAPORTHO\n"
1307 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1308 "#  else\n"
1309 "       return f;\n"
1310 "#  endif\n"
1311 "}\n"
1312 "# endif\n"
1313 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1314 "#endif // FRAGMENT_SHADER\n"
1315 "\n"
1316 "\n"
1317 "\n"
1318 "\n"
1319 "#ifdef MODE_DEFERREDGEOMETRY\n"
1320 "#ifdef VERTEX_SHADER\n"
1321 "uniform mat4 TexMatrix;\n"
1322 "#ifdef USEVERTEXTEXTUREBLEND\n"
1323 "uniform mat4 BackgroundTexMatrix;\n"
1324 "#endif\n"
1325 "uniform mat4 ModelViewMatrix;\n"
1326 "void main(void)\n"
1327 "{\n"
1328 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1329 "#ifdef USEVERTEXTEXTUREBLEND\n"
1330 "       gl_FrontColor = gl_Color;\n"
1331 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1332 "#endif\n"
1333 "\n"
1334 "       // transform unnormalized eye direction into tangent space\n"
1335 "#ifdef USEOFFSETMAPPING\n"
1336 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1337 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1338 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1339 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1340 "#endif\n"
1341 "\n"
1342 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1343 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1344 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1345 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1346 "}\n"
1347 "#endif // VERTEX_SHADER\n"
1348 "\n"
1349 "#ifdef FRAGMENT_SHADER\n"
1350 "void main(void)\n"
1351 "{\n"
1352 "#ifdef USEOFFSETMAPPING\n"
1353 "       // apply offsetmapping\n"
1354 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1355 "#define TexCoord TexCoordOffset\n"
1356 "#endif\n"
1357 "\n"
1358 "#ifdef USEALPHAKILL\n"
1359 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1360 "               discard;\n"
1361 "#endif\n"
1362 "\n"
1363 "#ifdef USEVERTEXTEXTUREBLEND\n"
1364 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1365 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1366 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1367 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1368 "#endif\n"
1369 "\n"
1370 "#ifdef USEVERTEXTEXTUREBLEND\n"
1371 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1372 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1373 "#else\n"
1374 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1375 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1376 "#endif\n"
1377 "\n"
1378 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1379 "}\n"
1380 "#endif // FRAGMENT_SHADER\n"
1381 "#else // !MODE_DEFERREDGEOMETRY\n"
1382 "\n"
1383 "\n"
1384 "\n"
1385 "\n"
1386 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1387 "#ifdef VERTEX_SHADER\n"
1388 "uniform mat4 ModelViewMatrix;\n"
1389 "void main(void)\n"
1390 "{\n"
1391 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1392 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1393 "}\n"
1394 "#endif // VERTEX_SHADER\n"
1395 "\n"
1396 "#ifdef FRAGMENT_SHADER\n"
1397 "uniform mat4 ViewToLight;\n"
1398 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1399 "uniform vec2 ScreenToDepth;\n"
1400 "uniform myhalf3 DeferredColor_Ambient;\n"
1401 "uniform myhalf3 DeferredColor_Diffuse;\n"
1402 "#ifdef USESPECULAR\n"
1403 "uniform myhalf3 DeferredColor_Specular;\n"
1404 "uniform myhalf SpecularPower;\n"
1405 "#endif\n"
1406 "uniform myhalf2 PixelToScreenTexCoord;\n"
1407 "void main(void)\n"
1408 "{\n"
1409 "       // calculate viewspace pixel position\n"
1410 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1411 "       vec3 position;\n"
1412 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1413 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1414 "       // decode viewspace pixel normal\n"
1415 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1416 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1417 "       // surfacenormal = pixel normal in viewspace\n"
1418 "       // LightVector = pixel to light in viewspace\n"
1419 "       // CubeVector = position in lightspace\n"
1420 "       // eyevector = pixel to view in viewspace\n"
1421 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1422 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1423 "#ifdef USEDIFFUSE\n"
1424 "       // calculate diffuse shading\n"
1425 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1426 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1427 "#endif\n"
1428 "#ifdef USESPECULAR\n"
1429 "       // calculate directional shading\n"
1430 "       vec3 eyevector = position * -1.0;\n"
1431 "#  ifdef USEEXACTSPECULARMATH\n"
1432 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1433 "#  else\n"
1434 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1435 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1436 "#  endif\n"
1437 "#endif\n"
1438 "\n"
1439 "#if defined(USESHADOWMAP2D)\n"
1440 "       fade *= ShadowMapCompare(CubeVector);\n"
1441 "#endif\n"
1442 "\n"
1443 "#ifdef USEDIFFUSE\n"
1444 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1445 "#else\n"
1446 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1447 "#endif\n"
1448 "#ifdef USESPECULAR\n"
1449 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1450 "#else\n"
1451 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1452 "#endif\n"
1453 "\n"
1454 "# ifdef USECUBEFILTER\n"
1455 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1456 "       gl_FragData[0].rgb *= cubecolor;\n"
1457 "       gl_FragData[1].rgb *= cubecolor;\n"
1458 "# endif\n"
1459 "}\n"
1460 "#endif // FRAGMENT_SHADER\n"
1461 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1462 "\n"
1463 "\n"
1464 "\n"
1465 "\n"
1466 "#ifdef VERTEX_SHADER\n"
1467 "uniform mat4 TexMatrix;\n"
1468 "#ifdef USEVERTEXTEXTUREBLEND\n"
1469 "uniform mat4 BackgroundTexMatrix;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTSOURCE\n"
1472 "uniform mat4 ModelToLight;\n"
1473 "#endif\n"
1474 "#ifdef USESHADOWMAPORTHO\n"
1475 "uniform mat4 ShadowMapMatrix;\n"
1476 "#endif\n"
1477 "void main(void)\n"
1478 "{\n"
1479 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1480 "       gl_FrontColor = gl_Color;\n"
1481 "#endif\n"
1482 "       // copy the surface texcoord\n"
1483 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1484 "#ifdef USEVERTEXTEXTUREBLEND\n"
1485 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1486 "#endif\n"
1487 "#ifdef USELIGHTMAP\n"
1488 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1489 "#endif\n"
1490 "\n"
1491 "#ifdef MODE_LIGHTSOURCE\n"
1492 "       // transform vertex position into light attenuation/cubemap space\n"
1493 "       // (-1 to +1 across the light box)\n"
1494 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1495 "\n"
1496 "# ifdef USEDIFFUSE\n"
1497 "       // transform unnormalized light direction into tangent space\n"
1498 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1499 "       //  normalize it per pixel)\n"
1500 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1501 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1502 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1503 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1504 "# endif\n"
1505 "#endif\n"
1506 "\n"
1507 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1508 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1509 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1510 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1511 "#endif\n"
1512 "\n"
1513 "       // transform unnormalized eye direction into tangent space\n"
1514 "#ifdef USEEYEVECTOR\n"
1515 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1516 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1517 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1518 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1519 "#endif\n"
1520 "\n"
1521 "#ifdef USEFOG\n"
1522 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1523 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1524 "#endif\n"
1525 "\n"
1526 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1527 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1528 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1529 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1530 "#endif\n"
1531 "\n"
1532 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1533 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1534 "\n"
1535 "#ifdef USESHADOWMAPORTHO\n"
1536 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1537 "#endif\n"
1538 "\n"
1539 "#ifdef USEREFLECTION\n"
1540 "       ModelViewProjectionPosition = gl_Position;\n"
1541 "#endif\n"
1542 "}\n"
1543 "#endif // VERTEX_SHADER\n"
1544 "\n"
1545 "\n"
1546 "\n"
1547 "\n"
1548 "#ifdef FRAGMENT_SHADER\n"
1549 "#ifdef USEDEFERREDLIGHTMAP\n"
1550 "uniform myhalf2 PixelToScreenTexCoord;\n"
1551 "uniform myhalf3 DeferredMod_Diffuse;\n"
1552 "uniform myhalf3 DeferredMod_Specular;\n"
1553 "#endif\n"
1554 "uniform myhalf3 Color_Ambient;\n"
1555 "uniform myhalf3 Color_Diffuse;\n"
1556 "uniform myhalf3 Color_Specular;\n"
1557 "uniform myhalf SpecularPower;\n"
1558 "#ifdef USEGLOW\n"
1559 "uniform myhalf3 Color_Glow;\n"
1560 "#endif\n"
1561 "uniform myhalf Alpha;\n"
1562 "#ifdef USEREFLECTION\n"
1563 "uniform vec4 DistortScaleRefractReflect;\n"
1564 "uniform vec4 ScreenScaleRefractReflect;\n"
1565 "uniform vec4 ScreenCenterRefractReflect;\n"
1566 "uniform myhalf4 ReflectColor;\n"
1567 "#endif\n"
1568 "#ifdef USEREFLECTCUBE\n"
1569 "uniform mat4 ModelToReflectCube;\n"
1570 "uniform sampler2D Texture_ReflectMask;\n"
1571 "uniform samplerCube Texture_ReflectCube;\n"
1572 "#endif\n"
1573 "#ifdef MODE_LIGHTDIRECTION\n"
1574 "uniform myhalf3 LightColor;\n"
1575 "#endif\n"
1576 "#ifdef MODE_LIGHTSOURCE\n"
1577 "uniform myhalf3 LightColor;\n"
1578 "#endif\n"
1579 "void main(void)\n"
1580 "{\n"
1581 "#ifdef USEOFFSETMAPPING\n"
1582 "       // apply offsetmapping\n"
1583 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1584 "#define TexCoord TexCoordOffset\n"
1585 "#endif\n"
1586 "\n"
1587 "       // combine the diffuse textures (base, pants, shirt)\n"
1588 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1589 "#ifdef USEALPHAKILL\n"
1590 "       if (color.a < 0.5)\n"
1591 "               discard;\n"
1592 "#endif\n"
1593 "       color.a *= Alpha;\n"
1594 "#ifdef USECOLORMAPPING\n"
1595 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1596 "#endif\n"
1597 "#ifdef USEVERTEXTEXTUREBLEND\n"
1598 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1599 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1600 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1601 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1602 "       color.a = 1.0;\n"
1603 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1604 "#endif\n"
1605 "\n"
1606 "       // get the surface normal\n"
1607 "#ifdef USEVERTEXTEXTUREBLEND\n"
1608 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1609 "#else\n"
1610 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1611 "#endif\n"
1612 "\n"
1613 "       // get the material colors\n"
1614 "       myhalf3 diffusetex = color.rgb;\n"
1615 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1616 "# ifdef USEVERTEXTEXTUREBLEND\n"
1617 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1618 "# else\n"
1619 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1620 "# endif\n"
1621 "#endif\n"
1622 "\n"
1623 "#ifdef USEREFLECTCUBE\n"
1624 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1625 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1626 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1627 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1628 "#endif\n"
1629 "\n"
1630 "\n"
1631 "\n"
1632 "\n"
1633 "#ifdef MODE_LIGHTSOURCE\n"
1634 "       // light source\n"
1635 "#ifdef USEDIFFUSE\n"
1636 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1637 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1638 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1639 "#ifdef USESPECULAR\n"
1640 "#ifdef USEEXACTSPECULARMATH\n"
1641 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1642 "#else\n"
1643 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1644 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1645 "#endif\n"
1646 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1647 "#endif\n"
1648 "#else\n"
1649 "       color.rgb = diffusetex * Color_Ambient;\n"
1650 "#endif\n"
1651 "       color.rgb *= LightColor;\n"
1652 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1653 "#if defined(USESHADOWMAP2D)\n"
1654 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1655 "#endif\n"
1656 "# ifdef USECUBEFILTER\n"
1657 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1658 "# endif\n"
1659 "#endif // MODE_LIGHTSOURCE\n"
1660 "\n"
1661 "\n"
1662 "\n"
1663 "\n"
1664 "#ifdef MODE_LIGHTDIRECTION\n"
1665 "#define SHADING\n"
1666 "#ifdef USEDIFFUSE\n"
1667 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1668 "#endif\n"
1669 "#define lightcolor LightColor\n"
1670 "#endif // MODE_LIGHTDIRECTION\n"
1671 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1672 "#define SHADING\n"
1673 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1674 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1675 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1676 "       // convert modelspace light vector to tangentspace\n"
1677 "       myhalf3 lightnormal;\n"
1678 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1679 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1680 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1681 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1682 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1683 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1684 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1685 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1686 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1687 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1688 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1689 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1690 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1691 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1692 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1693 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1694 "#define SHADING\n"
1695 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1696 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1697 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1698 "#endif\n"
1699 "\n"
1700 "\n"
1701 "\n"
1702 "\n"
1703 "#ifdef MODE_FAKELIGHT\n"
1704 "#define SHADING\n"
1705 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1706 "myhalf3 lightcolor = myhalf3(1.0);\n"
1707 "#endif // MODE_FAKELIGHT\n"
1708 "\n"
1709 "\n"
1710 "\n"
1711 "\n"
1712 "#ifdef MODE_LIGHTMAP\n"
1713 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1714 "#endif // MODE_LIGHTMAP\n"
1715 "#ifdef MODE_VERTEXCOLOR\n"
1716 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1717 "#endif // MODE_VERTEXCOLOR\n"
1718 "#ifdef MODE_FLATCOLOR\n"
1719 "       color.rgb = diffusetex * Color_Ambient;\n"
1720 "#endif // MODE_FLATCOLOR\n"
1721 "\n"
1722 "\n"
1723 "\n"
1724 "\n"
1725 "#ifdef SHADING\n"
1726 "# ifdef USEDIFFUSE\n"
1727 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1728 "#  ifdef USESPECULAR\n"
1729 "#   ifdef USEEXACTSPECULARMATH\n"
1730 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1731 "#   else\n"
1732 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1733 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1734 "#   endif\n"
1735 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1736 "#  else\n"
1737 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1738 "#  endif\n"
1739 "# else\n"
1740 "       color.rgb = diffusetex * Color_Ambient;\n"
1741 "# endif\n"
1742 "#endif\n"
1743 "\n"
1744 "#ifdef USESHADOWMAPORTHO\n"
1745 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1746 "#endif\n"
1747 "\n"
1748 "#ifdef USEDEFERREDLIGHTMAP\n"
1749 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1750 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1751 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1752 "#endif\n"
1753 "\n"
1754 "#ifdef USEGLOW\n"
1755 "#ifdef USEVERTEXTEXTUREBLEND\n"
1756 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1757 "#else\n"
1758 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1759 "#endif\n"
1760 "#endif\n"
1761 "\n"
1762 "#ifdef USEFOG\n"
1763 "       color.rgb = FogVertex(color.rgb);\n"
1764 "#endif\n"
1765 "\n"
1766 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1767 "#ifdef USEREFLECTION\n"
1768 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1769 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1770 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1771 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1772 "       // FIXME temporary hack to detect the case that the reflection\n"
1773 "       // gets blackened at edges due to leaving the area that contains actual\n"
1774 "       // content.\n"
1775 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1776 "       // 'appening.\n"
1777 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1778 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1779 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1780 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1781 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1782 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1783 "#endif\n"
1784 "\n"
1785 "       gl_FragColor = vec4(color);\n"
1786 "}\n"
1787 "#endif // FRAGMENT_SHADER\n"
1788 "\n"
1789 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1790 "#endif // !MODE_DEFERREDGEOMETRY\n"
1791 "#endif // !MODE_WATER\n"
1792 "#endif // !MODE_REFRACTION\n"
1793 "#endif // !MODE_BLOOMBLUR\n"
1794 "#endif // !MODE_GENERIC\n"
1795 "#endif // !MODE_POSTPROCESS\n"
1796 "#endif // !MODE_SHOWDEPTH\n"
1797 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1798 ;
1799
1800 /*
1801 =========================================================================================================================================================
1802
1803
1804
1805 =========================================================================================================================================================
1806
1807
1808
1809 =========================================================================================================================================================
1810
1811
1812
1813 =========================================================================================================================================================
1814
1815
1816
1817 =========================================================================================================================================================
1818
1819
1820
1821 =========================================================================================================================================================
1822
1823
1824
1825 =========================================================================================================================================================
1826 */
1827
1828 const char *builtincgshaderstring =
1829 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1830 "// written by Forest 'LordHavoc' Hale\n"
1831 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1832 "\n"
1833 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1834 "#if defined(USEREFLECTION)\n"
1835 "#undef USESHADOWMAPORTHO\n"
1836 "#endif\n"
1837 "\n"
1838 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1839 "# define USEFOG\n"
1840 "#endif\n"
1841 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1842 "#define USELIGHTMAP\n"
1843 "#endif\n"
1844 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1845 "#define USEEYEVECTOR\n"
1846 "#endif\n"
1847 "\n"
1848 "#ifdef FRAGMENT_SHADER\n"
1849 "#ifdef HLSL\n"
1850 "//#undef USESHADOWMAPPCF\n"
1851 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1852 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1853 "#else\n"
1854 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1855 "#endif\n"
1856 "#endif\n"
1857 "\n"
1858 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1859 "#ifdef VERTEX_SHADER\n"
1860 "void main\n"
1861 "(\n"
1862 "float4 gl_Vertex : POSITION,\n"
1863 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1864 "out float4 gl_Position : POSITION,\n"
1865 "out float Depth : TEXCOORD0\n"
1866 ")\n"
1867 "{\n"
1868 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1869 "       Depth = gl_Position.z;\n"
1870 "}\n"
1871 "#endif\n"
1872 "\n"
1873 "#ifdef FRAGMENT_SHADER\n"
1874 "void main\n"
1875 "(\n"
1876 "float Depth : TEXCOORD0,\n"
1877 "out float4 gl_FragColor : COLOR\n"
1878 ")\n"
1879 "{\n"
1880 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1881 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1882 "       temp.yz -= floor(temp.yz);\n"
1883 "       gl_FragColor = temp;\n"
1884 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1885 "}\n"
1886 "#endif\n"
1887 "#else // !MODE_DEPTH_ORSHADOW\n"
1888 "\n"
1889 "\n"
1890 "\n"
1891 "\n"
1892 "#ifdef MODE_SHOWDEPTH\n"
1893 "#ifdef VERTEX_SHADER\n"
1894 "void main\n"
1895 "(\n"
1896 "float4 gl_Vertex : POSITION,\n"
1897 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1898 "out float4 gl_Position : POSITION,\n"
1899 "out float4 gl_FrontColor : COLOR0\n"
1900 ")\n"
1901 "{\n"
1902 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1903 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1904 "}\n"
1905 "#endif\n"
1906 "\n"
1907 "#ifdef FRAGMENT_SHADER\n"
1908 "void main\n"
1909 "(\n"
1910 "float4 gl_FrontColor : COLOR0,\n"
1911 "out float4 gl_FragColor : COLOR\n"
1912 ")\n"
1913 "{\n"
1914 "       gl_FragColor = gl_FrontColor;\n"
1915 "}\n"
1916 "#endif\n"
1917 "#else // !MODE_SHOWDEPTH\n"
1918 "\n"
1919 "\n"
1920 "\n"
1921 "\n"
1922 "#ifdef MODE_POSTPROCESS\n"
1923 "\n"
1924 "#ifdef VERTEX_SHADER\n"
1925 "void main\n"
1926 "(\n"
1927 "float4 gl_Vertex : POSITION,\n"
1928 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1929 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1930 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1931 "out float4 gl_Position : POSITION,\n"
1932 "out float2 TexCoord1 : TEXCOORD0,\n"
1933 "out float2 TexCoord2 : TEXCOORD1\n"
1934 ")\n"
1935 "{\n"
1936 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1937 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1938 "#ifdef USEBLOOM\n"
1939 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1940 "#endif\n"
1941 "}\n"
1942 "#endif\n"
1943 "\n"
1944 "#ifdef FRAGMENT_SHADER\n"
1945 "void main\n"
1946 "(\n"
1947 "float2 TexCoord1 : TEXCOORD0,\n"
1948 "float2 TexCoord2 : TEXCOORD1,\n"
1949 "uniform sampler Texture_First : register(s0),\n"
1950 "#ifdef USEBLOOM\n"
1951 "uniform sampler Texture_Second : register(s1),\n"
1952 "#endif\n"
1953 "#ifdef USEGAMMARAMPS\n"
1954 "uniform sampler Texture_GammaRamps : register(s2),\n"
1955 "#endif\n"
1956 "#ifdef USESATURATION\n"
1957 "uniform float Saturation : register(c30),\n"
1958 "#endif\n"
1959 "#ifdef USEVIEWTINT\n"
1960 "uniform float4 ViewTintColor : register(c41),\n"
1961 "#endif\n"
1962 "uniform float4 UserVec1 : register(c37),\n"
1963 "uniform float4 UserVec2 : register(c38),\n"
1964 "uniform float4 UserVec3 : register(c39),\n"
1965 "uniform float4 UserVec4 : register(c40),\n"
1966 "uniform float ClientTime : register(c2),\n"
1967 "uniform float2 PixelSize : register(c25),\n"
1968 "uniform float4 BloomColorSubtract : register(c43),\n"
1969 "out float4 gl_FragColor : COLOR\n"
1970 ")\n"
1971 "{\n"
1972 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1973 "#ifdef USEBLOOM\n"
1974 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1975 "#endif\n"
1976 "#ifdef USEVIEWTINT\n"
1977 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1978 "#endif\n"
1979 "\n"
1980 "#ifdef USEPOSTPROCESSING\n"
1981 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1982 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1983 "       float sobel = 1.0;\n"
1984 "       // float2 ts = textureSize(Texture_First, 0);\n"
1985 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1986 "       float2 px = PixelSize;\n"
1987 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1988 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1989 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1990 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1991 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1992 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1993 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1994 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1995 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1996 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1997 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1998 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1999 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2000 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2001 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2002 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2003 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2004 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2005 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2006 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2007 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2008 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2009 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2010 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2011 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2012 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2013 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2014 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2015 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2016 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2017 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2018 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2019 "#endif\n"
2020 "\n"
2021 "#ifdef USESATURATION\n"
2022 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2023 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2024 "       // 'vampire sight' effect, wheres red is compensated\n"
2025 "       #ifdef SATURATION_REDCOMPENSATE\n"
2026 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2027 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2028 "               gl_FragColor.r += r;\n"
2029 "       #else\n"
2030 "               // normal desaturation\n"
2031 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2032 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2033 "       #endif\n"
2034 "#endif\n"
2035 "\n"
2036 "#ifdef USEGAMMARAMPS\n"
2037 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2038 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2039 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2040 "#endif\n"
2041 "}\n"
2042 "#endif\n"
2043 "#else // !MODE_POSTPROCESS\n"
2044 "\n"
2045 "\n"
2046 "\n"
2047 "\n"
2048 "#ifdef MODE_GENERIC\n"
2049 "#ifdef VERTEX_SHADER\n"
2050 "void main\n"
2051 "(\n"
2052 "float4 gl_Vertex : POSITION,\n"
2053 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2054 "float4 gl_Color : COLOR0,\n"
2055 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2056 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2057 "out float4 gl_Position : POSITION,\n"
2058 "#ifdef USEDIFFUSE\n"
2059 "out float2 TexCoord1 : TEXCOORD0,\n"
2060 "#endif\n"
2061 "#ifdef USESPECULAR\n"
2062 "out float2 TexCoord2 : TEXCOORD1,\n"
2063 "#endif\n"
2064 "out float4 gl_FrontColor : COLOR\n"
2065 ")\n"
2066 "{\n"
2067 "#ifdef HLSL\n"
2068 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2069 "#else\n"
2070 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2071 "#endif\n"
2072 "#ifdef USEDIFFUSE\n"
2073 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2074 "#endif\n"
2075 "#ifdef USESPECULAR\n"
2076 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2077 "#endif\n"
2078 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2079 "}\n"
2080 "#endif\n"
2081 "\n"
2082 "#ifdef FRAGMENT_SHADER\n"
2083 "\n"
2084 "void main\n"
2085 "(\n"
2086 "float4 gl_FrontColor : COLOR0,\n"
2087 "float2 TexCoord1 : TEXCOORD0,\n"
2088 "float2 TexCoord2 : TEXCOORD1,\n"
2089 "#ifdef USEDIFFUSE\n"
2090 "uniform sampler Texture_First : register(s0),\n"
2091 "#endif\n"
2092 "#ifdef USESPECULAR\n"
2093 "uniform sampler Texture_Second : register(s1),\n"
2094 "#endif\n"
2095 "out float4 gl_FragColor : COLOR\n"
2096 ")\n"
2097 "{\n"
2098 "#ifdef USEVIEWTINT\n"
2099 "       gl_FragColor = gl_FrontColor;\n"
2100 "#else\n"
2101 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2102 "#endif\n"
2103 "#ifdef USEDIFFUSE\n"
2104 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2105 "#endif\n"
2106 "\n"
2107 "#ifdef USESPECULAR\n"
2108 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2109 "# ifdef USECOLORMAPPING\n"
2110 "       gl_FragColor *= tex2;\n"
2111 "# endif\n"
2112 "# ifdef USEGLOW\n"
2113 "       gl_FragColor += tex2;\n"
2114 "# endif\n"
2115 "# ifdef USEVERTEXTEXTUREBLEND\n"
2116 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2117 "# endif\n"
2118 "#endif\n"
2119 "}\n"
2120 "#endif\n"
2121 "#else // !MODE_GENERIC\n"
2122 "\n"
2123 "\n"
2124 "\n"
2125 "\n"
2126 "#ifdef MODE_BLOOMBLUR\n"
2127 "#ifdef VERTEX_SHADER\n"
2128 "void main\n"
2129 "(\n"
2130 "float4 gl_Vertex : POSITION,\n"
2131 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2132 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2133 "out float4 gl_Position : POSITION,\n"
2134 "out float2 TexCoord : TEXCOORD0\n"
2135 ")\n"
2136 "{\n"
2137 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2138 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2139 "}\n"
2140 "#endif\n"
2141 "\n"
2142 "#ifdef FRAGMENT_SHADER\n"
2143 "\n"
2144 "void main\n"
2145 "(\n"
2146 "float2 TexCoord : TEXCOORD0,\n"
2147 "uniform sampler Texture_First : register(s0),\n"
2148 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2149 "out float4 gl_FragColor : COLOR\n"
2150 ")\n"
2151 "{\n"
2152 "       int i;\n"
2153 "       float2 tc = TexCoord;\n"
2154 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2155 "       tc += BloomBlur_Parameters.xy;\n"
2156 "       for (i = 1;i < SAMPLES;i++)\n"
2157 "       {\n"
2158 "               color += tex2D(Texture_First, tc).rgb;\n"
2159 "               tc += BloomBlur_Parameters.xy;\n"
2160 "       }\n"
2161 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2162 "}\n"
2163 "#endif\n"
2164 "#else // !MODE_BLOOMBLUR\n"
2165 "#ifdef MODE_REFRACTION\n"
2166 "#ifdef VERTEX_SHADER\n"
2167 "void main\n"
2168 "(\n"
2169 "float4 gl_Vertex : POSITION,\n"
2170 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2171 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2172 "uniform float4x4 TexMatrix : register(c0),\n"
2173 "uniform float3 EyePosition : register(c24),\n"
2174 "out float4 gl_Position : POSITION,\n"
2175 "out float2 TexCoord : TEXCOORD0,\n"
2176 "out float3 EyeVector : TEXCOORD1,\n"
2177 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2178 ")\n"
2179 "{\n"
2180 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2181 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2182 "       ModelViewProjectionPosition = gl_Position;\n"
2183 "}\n"
2184 "#endif\n"
2185 "\n"
2186 "#ifdef FRAGMENT_SHADER\n"
2187 "void main\n"
2188 "(\n"
2189 "float2 TexCoord : TEXCOORD0,\n"
2190 "float3 EyeVector : TEXCOORD1,\n"
2191 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2192 "uniform sampler Texture_Normal : register(s0),\n"
2193 "uniform sampler Texture_Refraction : register(s3),\n"
2194 "uniform sampler Texture_Reflection : register(s7),\n"
2195 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2196 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2197 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2198 "uniform float4 RefractColor : register(c29),\n"
2199 "out float4 gl_FragColor : COLOR\n"
2200 ")\n"
2201 "{\n"
2202 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2203 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2204 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2205 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2206 "       // FIXME temporary hack to detect the case that the reflection\n"
2207 "       // gets blackened at edges due to leaving the area that contains actual\n"
2208 "       // content.\n"
2209 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2210 "       // 'appening.\n"
2211 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2212 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2213 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2214 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2215 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2216 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2217 "}\n"
2218 "#endif\n"
2219 "#else // !MODE_REFRACTION\n"
2220 "\n"
2221 "\n"
2222 "\n"
2223 "\n"
2224 "#ifdef MODE_WATER\n"
2225 "#ifdef VERTEX_SHADER\n"
2226 "\n"
2227 "void main\n"
2228 "(\n"
2229 "float4 gl_Vertex : POSITION,\n"
2230 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2231 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2232 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2233 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2234 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2235 "uniform float4x4 TexMatrix : register(c0),\n"
2236 "uniform float3 EyePosition : register(c24),\n"
2237 "out float4 gl_Position : POSITION,\n"
2238 "out float2 TexCoord : TEXCOORD0,\n"
2239 "out float3 EyeVector : TEXCOORD1,\n"
2240 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2241 ")\n"
2242 "{\n"
2243 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2244 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2245 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2246 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2247 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2248 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2249 "       ModelViewProjectionPosition = gl_Position;\n"
2250 "}\n"
2251 "#endif\n"
2252 "\n"
2253 "#ifdef FRAGMENT_SHADER\n"
2254 "void main\n"
2255 "(\n"
2256 "float2 TexCoord : TEXCOORD0,\n"
2257 "float3 EyeVector : TEXCOORD1,\n"
2258 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2259 "uniform sampler Texture_Normal : register(s0),\n"
2260 "uniform sampler Texture_Refraction : register(s3),\n"
2261 "uniform sampler Texture_Reflection : register(s7),\n"
2262 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2263 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2264 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2265 "uniform float4 RefractColor : register(c29),\n"
2266 "uniform float4 ReflectColor : register(c26),\n"
2267 "uniform float ReflectFactor : register(c27),\n"
2268 "uniform float ReflectOffset : register(c28),\n"
2269 "out float4 gl_FragColor : COLOR\n"
2270 ")\n"
2271 "{\n"
2272 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2273 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2274 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2275 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2276 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2277 "       // FIXME temporary hack to detect the case that the reflection\n"
2278 "       // gets blackened at edges due to leaving the area that contains actual\n"
2279 "       // content.\n"
2280 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2281 "       // 'appening.\n"
2282 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2283 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2284 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2285 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2286 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2287 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2288 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2289 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2290 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2291 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2292 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2293 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2294 "}\n"
2295 "#endif\n"
2296 "#else // !MODE_WATER\n"
2297 "\n"
2298 "\n"
2299 "\n"
2300 "\n"
2301 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2302 "\n"
2303 "// fragment shader specific:\n"
2304 "#ifdef FRAGMENT_SHADER\n"
2305 "\n"
2306 "#ifdef USEFOG\n"
2307 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2308 "{\n"
2309 "       float fogfrac;\n"
2310 "#ifdef USEFOGHEIGHTTEXTURE\n"
2311 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2312 "       fogfrac = fogheightpixel.a;\n"
2313 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2314 "#else\n"
2315 "# ifdef USEFOGOUTSIDE\n"
2316 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2317 "# else\n"
2318 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2319 "# endif\n"
2320 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2321 "#endif\n"
2322 "}\n"
2323 "#endif\n"
2324 "\n"
2325 "#ifdef USEOFFSETMAPPING\n"
2326 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2327 "{\n"
2328 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2329 "       // 14 sample relief mapping: linear search and then binary search\n"
2330 "       // this basically steps forward a small amount repeatedly until it finds\n"
2331 "       // itself inside solid, then jitters forward and back using decreasing\n"
2332 "       // amounts to find the impact\n"
2333 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2334 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2335 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2336 "       float3 RT = float3(TexCoord, 1);\n"
2337 "       OffsetVector *= 0.1;\n"
2338 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2339 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2340 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2341 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2342 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2343 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2344 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2345 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2346 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2347 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2348 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2349 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2350 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2351 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2352 "       return RT.xy;\n"
2353 "#else\n"
2354 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2355 "       // this basically moves forward the full distance, and then backs up based\n"
2356 "       // on height of samples\n"
2357 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2358 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2359 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2360 "       TexCoord += OffsetVector;\n"
2361 "       OffsetVector *= 0.333;\n"
2362 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2363 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2364 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2365 "       return TexCoord;\n"
2366 "#endif\n"
2367 "}\n"
2368 "#endif // USEOFFSETMAPPING\n"
2369 "\n"
2370 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2371 "#if defined(USESHADOWMAP2D)\n"
2372 "# ifdef USESHADOWMAPORTHO\n"
2373 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2374 "# else\n"
2375 "#  ifdef USESHADOWMAPVSDCT\n"
2376 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2377 "{\n"
2378 "       float3 adir = abs(dir);\n"
2379 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2380 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2381 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2382 "}\n"
2383 "#  else\n"
2384 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2385 "{\n"
2386 "       float3 adir = abs(dir);\n"
2387 "       float ma = adir.z;\n"
2388 "       float4 proj = float4(dir, 2.5);\n"
2389 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2390 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2391 "#ifdef HLSL\n"
2392 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2393 "#else\n"
2394 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2395 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2396 "#endif\n"
2397 "}\n"
2398 "#  endif\n"
2399 "# endif\n"
2400 "#endif // defined(USESHADOWMAP2D)\n"
2401 "\n"
2402 "# ifdef USESHADOWMAP2D\n"
2403 "#ifdef USESHADOWMAPVSDCT\n"
2404 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2405 "#else\n"
2406 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2407 "#endif\n"
2408 "{\n"
2409 "#ifdef USESHADOWMAPVSDCT\n"
2410 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2411 "#else\n"
2412 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2413 "#endif\n"
2414 "       float f;\n"
2415 "\n"
2416 "#  ifdef USESHADOWSAMPLER\n"
2417 "#    ifdef USESHADOWMAPPCF\n"
2418 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2419 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2420 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2421 "#    else\n"
2422 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2423 "#    endif\n"
2424 "#  else\n"
2425 "#    ifdef USESHADOWMAPPCF\n"
2426 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2427 "#      ifdef GL_ARB_texture_gather\n"
2428 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2429 "#      else\n"
2430 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2431 "#      endif\n"
2432 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2433 "#      if USESHADOWMAPPCF > 1\n"
2434 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2435 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2436 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2437 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2438 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2439 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2440 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2441 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2442 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2443 "       float4 locols = float4(group1.ab, group3.ab);\n"
2444 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2445 "       locols.yz += group2.ab;\n"
2446 "       hicols.yz += group8.rg;\n"
2447 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2448 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2449 "                               lerp(locols, hicols, offset.y);\n"
2450 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2451 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2452 "       f = dot(cols, float4(1.0/25.0));\n"
2453 "#      else\n"
2454 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2455 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2456 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2457 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2458 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2459 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2460 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2461 "#      endif\n"
2462 "#     else\n"
2463 "#      ifdef GL_EXT_gpu_shader4\n"
2464 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2465 "#      else\n"
2466 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2467 "#      endif\n"
2468 "#      if USESHADOWMAPPCF > 1\n"
2469 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2470 "       center *= ShadowMap_TextureScale;\n"
2471 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2472 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2473 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2474 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2475 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2476 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2477 "#      else\n"
2478 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2479 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2480 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2481 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2482 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2483 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2484 "#      endif\n"
2485 "#     endif\n"
2486 "#    else\n"
2487 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2488 "#    endif\n"
2489 "#  endif\n"
2490 "#  ifdef USESHADOWMAPORTHO\n"
2491 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2492 "#  else\n"
2493 "       return f;\n"
2494 "#  endif\n"
2495 "}\n"
2496 "# endif\n"
2497 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2498 "#endif // FRAGMENT_SHADER\n"
2499 "\n"
2500 "\n"
2501 "\n"
2502 "\n"
2503 "#ifdef MODE_DEFERREDGEOMETRY\n"
2504 "#ifdef VERTEX_SHADER\n"
2505 "void main\n"
2506 "(\n"
2507 "float4 gl_Vertex : POSITION,\n"
2508 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2509 "#ifdef USEVERTEXTEXTUREBLEND\n"
2510 "float4 gl_Color : COLOR0,\n"
2511 "#endif\n"
2512 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2513 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2514 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2515 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2516 "uniform float4x4 TexMatrix : register(c0),\n"
2517 "#ifdef USEVERTEXTEXTUREBLEND\n"
2518 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2519 "#endif\n"
2520 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2521 "#ifdef USEOFFSETMAPPING\n"
2522 "uniform float3 EyePosition : register(c24),\n"
2523 "#endif\n"
2524 "out float4 gl_Position : POSITION,\n"
2525 "#ifdef USEVERTEXTEXTUREBLEND\n"
2526 "out float4 gl_FrontColor : COLOR,\n"
2527 "#endif\n"
2528 "out float4 TexCoordBoth : TEXCOORD0,\n"
2529 "#ifdef USEOFFSETMAPPING\n"
2530 "out float3 EyeVector : TEXCOORD2,\n"
2531 "#endif\n"
2532 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2533 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2534 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2535 ")\n"
2536 "{\n"
2537 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2538 "#ifdef USEVERTEXTEXTUREBLEND\n"
2539 "#ifdef HLSL\n"
2540 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2541 "#else\n"
2542 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2543 "#endif\n"
2544 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2545 "#endif\n"
2546 "\n"
2547 "       // transform unnormalized eye direction into tangent space\n"
2548 "#ifdef USEOFFSETMAPPING\n"
2549 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2550 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2551 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2552 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2553 "#endif\n"
2554 "\n"
2555 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2556 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2557 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2558 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2559 "       VectorR.w = gl_Position.z;\n"
2560 "}\n"
2561 "#endif // VERTEX_SHADER\n"
2562 "\n"
2563 "#ifdef FRAGMENT_SHADER\n"
2564 "void main\n"
2565 "(\n"
2566 "float4 TexCoordBoth : TEXCOORD0,\n"
2567 "float3 EyeVector : TEXCOORD2,\n"
2568 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2569 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2570 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2571 "uniform sampler Texture_Normal : register(s0),\n"
2572 "#ifdef USEALPHAKILL\n"
2573 "uniform sampler Texture_Color : register(s1),\n"
2574 "#endif\n"
2575 "uniform sampler Texture_Gloss : register(s2),\n"
2576 "#ifdef USEVERTEXTEXTUREBLEND\n"
2577 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2578 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2579 "#endif\n"
2580 "#ifdef USEOFFSETMAPPING\n"
2581 "uniform float OffsetMapping_Scale : register(c24),\n"
2582 "#endif\n"
2583 "uniform half SpecularPower : register(c36),\n"
2584 "#ifdef HLSL\n"
2585 "out float4 gl_FragData0 : COLOR0,\n"
2586 "out float4 gl_FragData1 : COLOR1\n"
2587 "#else\n"
2588 "out float4 gl_FragColor : COLOR\n"
2589 "#endif\n"
2590 ")\n"
2591 "{\n"
2592 "       float2 TexCoord = TexCoordBoth.xy;\n"
2593 "#ifdef USEOFFSETMAPPING\n"
2594 "       // apply offsetmapping\n"
2595 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2596 "#define TexCoord TexCoordOffset\n"
2597 "#endif\n"
2598 "\n"
2599 "#ifdef USEALPHAKILL\n"
2600 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2601 "               discard;\n"
2602 "#endif\n"
2603 "\n"
2604 "#ifdef USEVERTEXTEXTUREBLEND\n"
2605 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2606 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2607 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2608 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2609 "#endif\n"
2610 "\n"
2611 "#ifdef USEVERTEXTEXTUREBLEND\n"
2612 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2613 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2614 "#else\n"
2615 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2616 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2617 "#endif\n"
2618 "\n"
2619 "#ifdef HLSL\n"
2620 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2621 "       float Depth = VectorR.w / 256.0;\n"
2622 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2623 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2624 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2625 "       gl_FragData1 = depthcolor;\n"
2626 "#else\n"
2627 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2628 "#endif\n"
2629 "}\n"
2630 "#endif // FRAGMENT_SHADER\n"
2631 "#else // !MODE_DEFERREDGEOMETRY\n"
2632 "\n"
2633 "\n"
2634 "\n"
2635 "\n"
2636 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2637 "#ifdef VERTEX_SHADER\n"
2638 "void main\n"
2639 "(\n"
2640 "float4 gl_Vertex : POSITION,\n"
2641 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2642 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2643 "out float4 gl_Position : POSITION,\n"
2644 "out float4 ModelViewPosition : TEXCOORD0\n"
2645 ")\n"
2646 "{\n"
2647 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2648 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2649 "}\n"
2650 "#endif // VERTEX_SHADER\n"
2651 "\n"
2652 "#ifdef FRAGMENT_SHADER\n"
2653 "void main\n"
2654 "(\n"
2655 "#ifdef HLSL\n"
2656 "float2 Pixel : VPOS,\n"
2657 "#else\n"
2658 "float2 Pixel : WPOS,\n"
2659 "#endif\n"
2660 "float4 ModelViewPosition : TEXCOORD0,\n"
2661 "uniform float4x4 ViewToLight : register(c44),\n"
2662 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2663 "uniform float3 LightPosition : register(c23),\n"
2664 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2665 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2666 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2667 "#ifdef USESPECULAR\n"
2668 "uniform half3 DeferredColor_Specular : register(c11),\n"
2669 "uniform half SpecularPower : register(c36),\n"
2670 "#endif\n"
2671 "uniform sampler Texture_Attenuation : register(s9),\n"
2672 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2673 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2674 "\n"
2675 "#ifdef USECUBEFILTER\n"
2676 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2677 "#endif\n"
2678 "\n"
2679 "#ifdef USESHADOWMAP2D\n"
2680 "# ifdef USESHADOWSAMPLER\n"
2681 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2682 "# else\n"
2683 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2684 "# endif\n"
2685 "#endif\n"
2686 "\n"
2687 "#ifdef USESHADOWMAPVSDCT\n"
2688 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2689 "#endif\n"
2690 "\n"
2691 "#if defined(USESHADOWMAP2D)\n"
2692 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2693 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2694 "#endif\n"
2695 "\n"
2696 "out float4 gl_FragData0 : COLOR0,\n"
2697 "out float4 gl_FragData1 : COLOR1\n"
2698 ")\n"
2699 "{\n"
2700 "       // calculate viewspace pixel position\n"
2701 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2702 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2703 "       float3 position;\n"
2704 "#ifdef HLSL\n"
2705 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2706 "#else\n"
2707 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2708 "#endif\n"
2709 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2710 "       // decode viewspace pixel normal\n"
2711 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2712 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2713 "       // surfacenormal = pixel normal in viewspace\n"
2714 "       // LightVector = pixel to light in viewspace\n"
2715 "       // CubeVector = position in lightspace\n"
2716 "       // eyevector = pixel to view in viewspace\n"
2717 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2718 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2719 "#ifdef USEDIFFUSE\n"
2720 "       // calculate diffuse shading\n"
2721 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2722 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2723 "#endif\n"
2724 "#ifdef USESPECULAR\n"
2725 "       // calculate directional shading\n"
2726 "       float3 eyevector = position * -1.0;\n"
2727 "#  ifdef USEEXACTSPECULARMATH\n"
2728 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2729 "#  else\n"
2730 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2731 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2732 "#  endif\n"
2733 "#endif\n"
2734 "\n"
2735 "#if defined(USESHADOWMAP2D)\n"
2736 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2737 "#ifdef USESHADOWMAPVSDCT\n"
2738 ", Texture_CubeProjection\n"
2739 "#endif\n"
2740 "       ));\n"
2741 "#endif\n"
2742 "\n"
2743 "#ifdef USEDIFFUSE\n"
2744 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2745 "#else\n"
2746 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2747 "#endif\n"
2748 "#ifdef USESPECULAR\n"
2749 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2750 "#else\n"
2751 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2752 "#endif\n"
2753 "\n"
2754 "# ifdef USECUBEFILTER\n"
2755 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2756 "       gl_FragData0.rgb *= cubecolor;\n"
2757 "       gl_FragData1.rgb *= cubecolor;\n"
2758 "# endif\n"
2759 "}\n"
2760 "#endif // FRAGMENT_SHADER\n"
2761 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2762 "\n"
2763 "\n"
2764 "\n"
2765 "\n"
2766 "#ifdef VERTEX_SHADER\n"
2767 "void main\n"
2768 "(\n"
2769 "float4 gl_Vertex : POSITION,\n"
2770 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2771 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2772 "float4 gl_Color : COLOR0,\n"
2773 "#endif\n"
2774 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2775 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2776 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2777 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2778 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2779 "\n"
2780 "uniform float3 EyePosition : register(c24),\n"
2781 "uniform float4x4 TexMatrix : register(c0),\n"
2782 "#ifdef USEVERTEXTEXTUREBLEND\n"
2783 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2784 "#endif\n"
2785 "#ifdef MODE_LIGHTSOURCE\n"
2786 "uniform float4x4 ModelToLight : register(c20),\n"
2787 "#endif\n"
2788 "#ifdef MODE_LIGHTSOURCE\n"
2789 "uniform float3 LightPosition : register(c27),\n"
2790 "#endif\n"
2791 "#ifdef MODE_LIGHTDIRECTION\n"
2792 "uniform float3 LightDir : register(c26),\n"
2793 "#endif\n"
2794 "uniform float4 FogPlane : register(c25),\n"
2795 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2796 "uniform float3 LightPosition : register(c27),\n"
2797 "#endif\n"
2798 "#ifdef USESHADOWMAPORTHO\n"
2799 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2800 "#endif\n"
2801 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2802 "out float4 gl_FrontColor : COLOR,\n"
2803 "#endif\n"
2804 "out float4 TexCoordBoth : TEXCOORD0,\n"
2805 "#ifdef USELIGHTMAP\n"
2806 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2807 "#endif\n"
2808 "#ifdef USEEYEVECTOR\n"
2809 "out float3 EyeVector : TEXCOORD2,\n"
2810 "#endif\n"
2811 "#ifdef USEREFLECTION\n"
2812 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2813 "#endif\n"
2814 "#ifdef USEFOG\n"
2815 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2816 "#endif\n"
2817 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2818 "out float3 LightVector : TEXCOORD1,\n"
2819 "#endif\n"
2820 "#ifdef MODE_LIGHTSOURCE\n"
2821 "out float3 CubeVector : TEXCOORD3,\n"
2822 "#endif\n"
2823 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2824 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2825 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2826 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2827 "#endif\n"
2828 "#ifdef USESHADOWMAPORTHO\n"
2829 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2830 "#endif\n"
2831 "out float4 gl_Position : POSITION\n"
2832 ")\n"
2833 "{\n"
2834 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2835 "#ifdef HLSL\n"
2836 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2837 "#else\n"
2838 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2839 "#endif\n"
2840 "#endif\n"
2841 "       // copy the surface texcoord\n"
2842 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2843 "#ifdef USEVERTEXTEXTUREBLEND\n"
2844 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2845 "#endif\n"
2846 "#ifdef USELIGHTMAP\n"
2847 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2848 "#endif\n"
2849 "\n"
2850 "#ifdef MODE_LIGHTSOURCE\n"
2851 "       // transform vertex position into light attenuation/cubemap space\n"
2852 "       // (-1 to +1 across the light box)\n"
2853 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2854 "\n"
2855 "# ifdef USEDIFFUSE\n"
2856 "       // transform unnormalized light direction into tangent space\n"
2857 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2858 "       //  normalize it per pixel)\n"
2859 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2860 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2861 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2862 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2863 "# endif\n"
2864 "#endif\n"
2865 "\n"
2866 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2867 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2868 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2869 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2870 "#endif\n"
2871 "\n"
2872 "       // transform unnormalized eye direction into tangent space\n"
2873 "#ifdef USEEYEVECTOR\n"
2874 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2875 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2876 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2877 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2878 "#endif\n"
2879 "\n"
2880 "#ifdef USEFOG\n"
2881 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2882 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2883 "#endif\n"
2884 "\n"
2885 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2886 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2887 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2888 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2889 "#endif\n"
2890 "\n"
2891 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2892 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2893 "\n"
2894 "#ifdef USESHADOWMAPORTHO\n"
2895 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2896 "#endif\n"
2897 "\n"
2898 "#ifdef USEREFLECTION\n"
2899 "       ModelViewProjectionPosition = gl_Position;\n"
2900 "#endif\n"
2901 "}\n"
2902 "#endif // VERTEX_SHADER\n"
2903 "\n"
2904 "\n"
2905 "\n"
2906 "\n"
2907 "#ifdef FRAGMENT_SHADER\n"
2908 "void main\n"
2909 "(\n"
2910 "#ifdef USEDEFERREDLIGHTMAP\n"
2911 "#ifdef HLSL\n"
2912 "float2 Pixel : VPOS,\n"
2913 "#else\n"
2914 "float2 Pixel : WPOS,\n"
2915 "#endif\n"
2916 "#endif\n"
2917 "float4 gl_FrontColor : COLOR,\n"
2918 "float4 TexCoordBoth : TEXCOORD0,\n"
2919 "#ifdef USELIGHTMAP\n"
2920 "float2 TexCoordLightmap : TEXCOORD1,\n"
2921 "#endif\n"
2922 "#ifdef USEEYEVECTOR\n"
2923 "float3 EyeVector : TEXCOORD2,\n"
2924 "#endif\n"
2925 "#ifdef USEREFLECTION\n"
2926 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2927 "#endif\n"
2928 "#ifdef USEFOG\n"
2929 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2930 "#endif\n"
2931 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2932 "float3 LightVector : TEXCOORD1,\n"
2933 "#endif\n"
2934 "#ifdef MODE_LIGHTSOURCE\n"
2935 "float3 CubeVector : TEXCOORD3,\n"
2936 "#endif\n"
2937 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2938 "float4 ModelViewPosition : TEXCOORD0,\n"
2939 "#endif\n"
2940 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2941 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2942 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2943 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2944 "#endif\n"
2945 "#ifdef USESHADOWMAPORTHO\n"
2946 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2947 "#endif\n"
2948 "\n"
2949 "uniform sampler Texture_Normal : register(s0),\n"
2950 "uniform sampler Texture_Color : register(s1),\n"
2951 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2952 "uniform sampler Texture_Gloss : register(s2),\n"
2953 "#endif\n"
2954 "#ifdef USEGLOW\n"
2955 "uniform sampler Texture_Glow : register(s3),\n"
2956 "#endif\n"
2957 "#ifdef USEVERTEXTEXTUREBLEND\n"
2958 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2959 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2960 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2961 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2962 "#endif\n"
2963 "#ifdef USEGLOW\n"
2964 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2965 "#endif\n"
2966 "#endif\n"
2967 "#ifdef USECOLORMAPPING\n"
2968 "uniform sampler Texture_Pants : register(s4),\n"
2969 "uniform sampler Texture_Shirt : register(s7),\n"
2970 "#endif\n"
2971 "#ifdef USEFOG\n"
2972 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2973 "uniform sampler Texture_FogMask : register(s8),\n"
2974 "#endif\n"
2975 "#ifdef USELIGHTMAP\n"
2976 "uniform sampler Texture_Lightmap : register(s9),\n"
2977 "#endif\n"
2978 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2979 "uniform sampler Texture_Deluxemap : register(s10),\n"
2980 "#endif\n"
2981 "#ifdef USEREFLECTION\n"
2982 "uniform sampler Texture_Reflection : register(s7),\n"
2983 "#endif\n"
2984 "\n"
2985 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2986 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2987 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2988 "#endif\n"
2989 "#ifdef USEDEFERREDLIGHTMAP\n"
2990 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2991 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2992 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2993 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2994 "#endif\n"
2995 "\n"
2996 "#ifdef USECOLORMAPPING\n"
2997 "uniform half3 Color_Pants : register(c7),\n"
2998 "uniform half3 Color_Shirt : register(c8),\n"
2999 "#endif\n"
3000 "#ifdef USEFOG\n"
3001 "uniform float3 FogColor : register(c16),\n"
3002 "uniform float FogRangeRecip : register(c20),\n"
3003 "uniform float FogPlaneViewDist : register(c19),\n"
3004 "uniform float FogHeightFade : register(c17),\n"
3005 "#endif\n"
3006 "\n"
3007 "#ifdef USEOFFSETMAPPING\n"
3008 "uniform float OffsetMapping_Scale : register(c24),\n"
3009 "#endif\n"
3010 "\n"
3011 "#ifdef USEDEFERREDLIGHTMAP\n"
3012 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3013 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3014 "uniform half3 DeferredMod_Specular : register(c13),\n"
3015 "#endif\n"
3016 "uniform half3 Color_Ambient : register(c3),\n"
3017 "uniform half3 Color_Diffuse : register(c4),\n"
3018 "uniform half3 Color_Specular : register(c5),\n"
3019 "uniform half SpecularPower : register(c36),\n"
3020 "#ifdef USEGLOW\n"
3021 "uniform half3 Color_Glow : register(c6),\n"
3022 "#endif\n"
3023 "uniform half Alpha : register(c0),\n"
3024 "#ifdef USEREFLECTION\n"
3025 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3026 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3027 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3028 "uniform half4 ReflectColor : register(c26),\n"
3029 "#endif\n"
3030 "#ifdef USEREFLECTCUBE\n"
3031 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3032 "uniform sampler Texture_ReflectMask : register(s5),\n"
3033 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3034 "#endif\n"
3035 "#ifdef MODE_LIGHTDIRECTION\n"
3036 "uniform half3 LightColor : register(c21),\n"
3037 "#endif\n"
3038 "#ifdef MODE_LIGHTSOURCE\n"
3039 "uniform half3 LightColor : register(c21),\n"
3040 "#endif\n"
3041 "\n"
3042 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3043 "uniform sampler Texture_Attenuation : register(s9),\n"
3044 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3045 "#endif\n"
3046 "\n"
3047 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3048 "\n"
3049 "#ifdef USESHADOWMAP2D\n"
3050 "# ifdef USESHADOWSAMPLER\n"
3051 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3052 "# else\n"
3053 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3054 "# endif\n"
3055 "#endif\n"
3056 "\n"
3057 "#ifdef USESHADOWMAPVSDCT\n"
3058 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3059 "#endif\n"
3060 "\n"
3061 "#if defined(USESHADOWMAP2D)\n"
3062 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3063 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3064 "#endif\n"
3065 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3066 "\n"
3067 "out float4 gl_FragColor : COLOR\n"
3068 ")\n"
3069 "{\n"
3070 "       float2 TexCoord = TexCoordBoth.xy;\n"
3071 "#ifdef USEVERTEXTEXTUREBLEND\n"
3072 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3073 "#endif\n"
3074 "#ifdef USEOFFSETMAPPING\n"
3075 "       // apply offsetmapping\n"
3076 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3077 "#define TexCoord TexCoordOffset\n"
3078 "#endif\n"
3079 "\n"
3080 "       // combine the diffuse textures (base, pants, shirt)\n"
3081 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3082 "#ifdef USEALPHAKILL\n"
3083 "       if (color.a < 0.5)\n"
3084 "               discard;\n"
3085 "#endif\n"
3086 "       color.a *= Alpha;\n"
3087 "#ifdef USECOLORMAPPING\n"
3088 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3089 "#endif\n"
3090 "#ifdef USEVERTEXTEXTUREBLEND\n"
3091 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3092 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3093 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3094 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3095 "       color.a = 1.0;\n"
3096 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3097 "#endif\n"
3098 "\n"
3099 "       // get the surface normal\n"
3100 "#ifdef USEVERTEXTEXTUREBLEND\n"
3101 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3102 "#else\n"
3103 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3104 "#endif\n"
3105 "\n"
3106 "       // get the material colors\n"
3107 "       half3 diffusetex = color.rgb;\n"
3108 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3109 "# ifdef USEVERTEXTEXTUREBLEND\n"
3110 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3111 "# else\n"
3112 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3113 "# endif\n"
3114 "#endif\n"
3115 "\n"
3116 "#ifdef USEREFLECTCUBE\n"
3117 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3118 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3119 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3120 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3121 "#endif\n"
3122 "\n"
3123 "\n"
3124 "\n"
3125 "\n"
3126 "#ifdef MODE_LIGHTSOURCE\n"
3127 "       // light source\n"
3128 "#ifdef USEDIFFUSE\n"
3129 "       half3 lightnormal = half3(normalize(LightVector));\n"
3130 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3131 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3132 "#ifdef USESPECULAR\n"
3133 "#ifdef USEEXACTSPECULARMATH\n"
3134 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3135 "#else\n"
3136 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3137 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3138 "#endif\n"
3139 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3140 "#endif\n"
3141 "#else\n"
3142 "       color.rgb = diffusetex * Color_Ambient;\n"
3143 "#endif\n"
3144 "       color.rgb *= LightColor;\n"
3145 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3146 "#if defined(USESHADOWMAP2D)\n"
3147 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3148 "#ifdef USESHADOWMAPVSDCT\n"
3149 ", Texture_CubeProjection\n"
3150 "#endif\n"
3151 "       ));\n"
3152 "\n"
3153 "#endif\n"
3154 "# ifdef USECUBEFILTER\n"
3155 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3156 "# endif\n"
3157 "\n"
3158 "#ifdef USESHADOWMAP2D\n"
3159 "#ifdef USESHADOWMAPVSDCT\n"
3160 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3161 "#else\n"
3162 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3163 "#endif\n"
3164 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3165 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3166 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3167 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3168 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3169 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3170 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3171 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3172 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3173 "//     color.r = half(shadowmaptc.z);\n"
3174 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3175 "//     color.r = half(shadowmaptc.z);\n"
3176 "//     color.r = 1;\n"
3177 "//     color.rgb = abs(CubeVector);\n"
3178 "#endif\n"
3179 "//     color.rgb = half3(1,1,1);\n"
3180 "#endif // MODE_LIGHTSOURCE\n"
3181 "\n"
3182 "\n"
3183 "\n"
3184 "\n"
3185 "#ifdef MODE_LIGHTDIRECTION\n"
3186 "#define SHADING\n"
3187 "#ifdef USEDIFFUSE\n"
3188 "       half3 lightnormal = half3(normalize(LightVector));\n"
3189 "#endif\n"
3190 "#define lightcolor LightColor\n"
3191 "#endif // MODE_LIGHTDIRECTION\n"
3192 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3193 "#define SHADING\n"
3194 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3195 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3196 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3197 "       // convert modelspace light vector to tangentspace\n"
3198 "       half3 lightnormal;\n"
3199 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3200 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3201 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3202 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3203 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3204 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3205 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3206 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3207 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3208 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3209 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3210 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3211 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3212 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3213 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3214 "#define SHADING\n"
3215 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3216 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3217 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3218 "#endif\n"
3219 "\n"
3220 "\n"
3221 "\n"
3222 "\n"
3223 "#ifdef MODE_FAKELIGHT\n"
3224 "#define SHADING\n"
3225 "half3 lightnormal = half3(normalize(EyeVector));\n"
3226 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3227 "#endif // MODE_FAKELIGHT\n"
3228 "\n"
3229 "\n"
3230 "\n"
3231 "\n"
3232 "#ifdef MODE_LIGHTMAP\n"
3233 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3234 "#endif // MODE_LIGHTMAP\n"
3235 "#ifdef MODE_VERTEXCOLOR\n"
3236 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3237 "#endif // MODE_VERTEXCOLOR\n"
3238 "#ifdef MODE_FLATCOLOR\n"
3239 "       color.rgb = diffusetex * Color_Ambient;\n"
3240 "#endif // MODE_FLATCOLOR\n"
3241 "\n"
3242 "\n"
3243 "\n"
3244 "\n"
3245 "#ifdef SHADING\n"
3246 "# ifdef USEDIFFUSE\n"
3247 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3248 "#  ifdef USESPECULAR\n"
3249 "#   ifdef USEEXACTSPECULARMATH\n"
3250 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3251 "#   else\n"
3252 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3253 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3254 "#   endif\n"
3255 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3256 "#  else\n"
3257 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3258 "#  endif\n"
3259 "# else\n"
3260 "       color.rgb = diffusetex * Color_Ambient;\n"
3261 "# endif\n"
3262 "#endif\n"
3263 "\n"
3264 "#ifdef USESHADOWMAPORTHO\n"
3265 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3266 "#endif\n"
3267 "\n"
3268 "#ifdef USEDEFERREDLIGHTMAP\n"
3269 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3270 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3271 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3272 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3273 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3274 "#endif\n"
3275 "\n"
3276 "#ifdef USEGLOW\n"
3277 "#ifdef USEVERTEXTEXTUREBLEND\n"
3278 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3279 "#else\n"
3280 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3281 "#endif\n"
3282 "#endif\n"
3283 "\n"
3284 "#ifdef USEFOG\n"
3285 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3286 "#endif\n"
3287 "\n"
3288 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3289 "#ifdef USEREFLECTION\n"
3290 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3291 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3292 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3293 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3294 "       // FIXME temporary hack to detect the case that the reflection\n"
3295 "       // gets blackened at edges due to leaving the area that contains actual\n"
3296 "       // content.\n"
3297 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3298 "       // 'appening.\n"
3299 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3300 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3301 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3302 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3303 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3304 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3305 "#endif\n"
3306 "\n"
3307 "       gl_FragColor = float4(color);\n"
3308 "}\n"
3309 "#endif // FRAGMENT_SHADER\n"
3310 "\n"
3311 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3312 "#endif // !MODE_DEFERREDGEOMETRY\n"
3313 "#endif // !MODE_WATER\n"
3314 "#endif // !MODE_REFRACTION\n"
3315 "#endif // !MODE_BLOOMBLUR\n"
3316 "#endif // !MODE_GENERIC\n"
3317 "#endif // !MODE_POSTPROCESS\n"
3318 "#endif // !MODE_SHOWDEPTH\n"
3319 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3320 ;
3321
3322 char *glslshaderstring = NULL;
3323 char *cgshaderstring = NULL;
3324 char *hlslshaderstring = NULL;
3325
3326 //=======================================================================================================================================================
3327
3328 typedef struct shaderpermutationinfo_s
3329 {
3330         const char *pretext;
3331         const char *name;
3332 }
3333 shaderpermutationinfo_t;
3334
3335 typedef struct shadermodeinfo_s
3336 {
3337         const char *vertexfilename;
3338         const char *geometryfilename;
3339         const char *fragmentfilename;
3340         const char *pretext;
3341         const char *name;
3342 }
3343 shadermodeinfo_t;
3344
3345 typedef enum shaderpermutation_e
3346 {
3347         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3348         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3349         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only), use vertex colors (generic only)
3350         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3351         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3352         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3353         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3354         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3355         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3356         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3357         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3358         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3359         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3360         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3361         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3362         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3363         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3364         SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter
3365         SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results
3366         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3367         SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test
3368         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3369         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, //< (lightsource) use orthographic shadowmap projection
3370         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3371         SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3372         SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe)
3373         SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, // (water) counter-direction normalmaps scrolling
3374         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3375         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3376 }
3377 shaderpermutation_t;
3378
3379 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3380 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3381 {
3382         {"#define USEDIFFUSE\n", " diffuse"},
3383         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3384         {"#define USEVIEWTINT\n", " viewtint"},
3385         {"#define USECOLORMAPPING\n", " colormapping"},
3386         {"#define USESATURATION\n", " saturation"},
3387         {"#define USEFOGINSIDE\n", " foginside"},
3388         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3389         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3390         {"#define USEGAMMARAMPS\n", " gammaramps"},
3391         {"#define USECUBEFILTER\n", " cubefilter"},
3392         {"#define USEGLOW\n", " glow"},
3393         {"#define USEBLOOM\n", " bloom"},
3394         {"#define USESPECULAR\n", " specular"},
3395         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3396         {"#define USEREFLECTION\n", " reflection"},
3397         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3398         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3399         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3400         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3401         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3402         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3403         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3404         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3405         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3406         {"#define USEALPHAKILL\n", " alphakill"},
3407         {"#define USEREFLECTCUBE\n", " reflectcube"},
3408         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3409 };
3410
3411 // this enum selects which of the glslshadermodeinfo entries should be used
3412 typedef enum shadermode_e
3413 {
3414         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3415         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3416         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3417         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3418         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3419         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3420         SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3421         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3422         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3423         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3424         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3425         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3426         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3427         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3428         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3429         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3430         SHADERMODE_COUNT
3431 }
3432 shadermode_t;
3433
3434 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3435 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3436 {
3437         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3438         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3439         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3440         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3441         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3442         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3443         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3444         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3445         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3446         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3447         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3448         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3449         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3450         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3451         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3452         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3453 };
3454
3455 #ifdef SUPPORTCG
3456 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3457 {
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3460         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3461         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3462         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3463         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3464         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3465         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3466         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3467         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3468         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3469         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3470         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3471         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3472         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3473         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3474 };
3475 #endif
3476
3477 #ifdef SUPPORTD3D
3478 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3479 {
3480         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3481         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3482         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3483         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3484         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3485         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3486         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3487         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3488         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3489         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3490         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3491         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3492         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3493         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3494         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3495         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3496 };
3497 #endif
3498
3499 struct r_glsl_permutation_s;
3500 typedef struct r_glsl_permutation_s
3501 {
3502         /// hash lookup data
3503         struct r_glsl_permutation_s *hashnext;
3504         unsigned int mode;
3505         unsigned int permutation;
3506
3507         /// indicates if we have tried compiling this permutation already
3508         qboolean compiled;
3509         /// 0 if compilation failed
3510         int program;
3511         /// locations of detected uniforms in program object, or -1 if not found
3512         int loc_Texture_First;
3513         int loc_Texture_Second;
3514         int loc_Texture_GammaRamps;
3515         int loc_Texture_Normal;
3516         int loc_Texture_Color;
3517         int loc_Texture_Gloss;
3518         int loc_Texture_Glow;
3519         int loc_Texture_SecondaryNormal;
3520         int loc_Texture_SecondaryColor;
3521         int loc_Texture_SecondaryGloss;
3522         int loc_Texture_SecondaryGlow;
3523         int loc_Texture_Pants;
3524         int loc_Texture_Shirt;
3525         int loc_Texture_FogHeightTexture;
3526         int loc_Texture_FogMask;
3527         int loc_Texture_Lightmap;
3528         int loc_Texture_Deluxemap;
3529         int loc_Texture_Attenuation;
3530         int loc_Texture_Cube;
3531         int loc_Texture_Refraction;
3532         int loc_Texture_Reflection;
3533         int loc_Texture_ShadowMap2D;
3534         int loc_Texture_CubeProjection;
3535         int loc_Texture_ScreenDepth;
3536         int loc_Texture_ScreenNormalMap;
3537         int loc_Texture_ScreenDiffuse;
3538         int loc_Texture_ScreenSpecular;
3539         int loc_Texture_ReflectMask;
3540         int loc_Texture_ReflectCube;
3541         int loc_Alpha;
3542         int loc_BloomBlur_Parameters;
3543         int loc_ClientTime;
3544         int loc_Color_Ambient;
3545         int loc_Color_Diffuse;
3546         int loc_Color_Specular;
3547         int loc_Color_Glow;
3548         int loc_Color_Pants;
3549         int loc_Color_Shirt;
3550         int loc_DeferredColor_Ambient;
3551         int loc_DeferredColor_Diffuse;
3552         int loc_DeferredColor_Specular;
3553         int loc_DeferredMod_Diffuse;
3554         int loc_DeferredMod_Specular;
3555         int loc_DistortScaleRefractReflect;
3556         int loc_EyePosition;
3557         int loc_FogColor;
3558         int loc_FogHeightFade;
3559         int loc_FogPlane;
3560         int loc_FogPlaneViewDist;
3561         int loc_FogRangeRecip;
3562         int loc_LightColor;
3563         int loc_LightDir;
3564         int loc_LightPosition;
3565         int loc_OffsetMapping_Scale;
3566         int loc_PixelSize;
3567         int loc_ReflectColor;
3568         int loc_ReflectFactor;
3569         int loc_ReflectOffset;
3570         int loc_RefractColor;
3571         int loc_Saturation;
3572         int loc_ScreenCenterRefractReflect;
3573         int loc_ScreenScaleRefractReflect;
3574         int loc_ScreenToDepth;
3575         int loc_ShadowMap_Parameters;
3576         int loc_ShadowMap_TextureScale;
3577         int loc_SpecularPower;
3578         int loc_UserVec1;
3579         int loc_UserVec2;
3580         int loc_UserVec3;
3581         int loc_UserVec4;
3582         int loc_ViewTintColor;
3583         int loc_ViewToLight;
3584         int loc_ModelToLight;
3585         int loc_TexMatrix;
3586         int loc_BackgroundTexMatrix;
3587         int loc_ModelViewProjectionMatrix;
3588         int loc_ModelViewMatrix;
3589         int loc_PixelToScreenTexCoord;
3590         int loc_ModelToReflectCube;
3591         int loc_ShadowMapMatrix;
3592         int loc_BloomColorSubtract;
3593         int loc_NormalmapScrollBlend;
3594 }
3595 r_glsl_permutation_t;
3596
3597 #define SHADERPERMUTATION_HASHSIZE 256
3598
3599
3600 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3601 // these can NOT degrade! only use for simple stuff
3602 enum
3603 {
3604         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3605         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3606         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3607         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3608         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3609         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3610 };
3611 #define SHADERSTATICPARMS_COUNT 6
3612
3613 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3614 static int shaderstaticparms_count = 0;
3615
3616 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3617 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3618 qboolean R_CompileShader_CheckStaticParms(void)
3619 {
3620         static int r_compileshader_staticparms_save[1];
3621         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3622         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3623
3624         // detect all
3625         if (r_glsl_saturation_redcompensate.integer)
3626                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3627         if (r_shadow_glossexact.integer)
3628                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3629         if (r_glsl_postprocess.integer)
3630         {
3631                 if (r_glsl_postprocess_uservec1_enable.integer)
3632                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3633                 if (r_glsl_postprocess_uservec2_enable.integer)
3634                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3635                 if (r_glsl_postprocess_uservec3_enable.integer)
3636                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3637                 if (r_glsl_postprocess_uservec4_enable.integer)
3638                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3639         }
3640         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3641 }
3642
3643 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3644         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3645                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3646         else \
3647                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3648 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3649 {
3650         shaderstaticparms_count = 0;
3651
3652         // emit all
3653         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3654         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3655         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3656         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3657         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3658         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3659 }
3660
3661 /// information about each possible shader permutation
3662 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3663 /// currently selected permutation
3664 r_glsl_permutation_t *r_glsl_permutation;
3665 /// storage for permutations linked in the hash table
3666 memexpandablearray_t r_glsl_permutationarray;
3667
3668 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3669 {
3670         //unsigned int hashdepth = 0;
3671         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3672         r_glsl_permutation_t *p;
3673         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3674         {
3675                 if (p->mode == mode && p->permutation == permutation)
3676                 {
3677                         //if (hashdepth > 10)
3678                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3679                         return p;
3680                 }
3681                 //hashdepth++;
3682         }
3683         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3684         p->mode = mode;
3685         p->permutation = permutation;
3686         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3687         r_glsl_permutationhash[mode][hashindex] = p;
3688         //if (hashdepth > 10)
3689         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3690         return p;
3691 }
3692
3693 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3694 {
3695         char *shaderstring;
3696         if (!filename || !filename[0])
3697                 return NULL;
3698         if (!strcmp(filename, "glsl/default.glsl"))
3699         {
3700                 if (!glslshaderstring)
3701                 {
3702                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3703                         if (glslshaderstring)
3704                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3705                         else
3706                                 glslshaderstring = (char *)builtinshaderstring;
3707                 }
3708                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3709                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3710                 return shaderstring;
3711         }
3712         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3713         if (shaderstring)
3714         {
3715                 if (printfromdisknotice)
3716                         Con_DPrintf("from disk %s... ", filename);
3717                 return shaderstring;
3718         }
3719         return shaderstring;
3720 }
3721
3722 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3723 {
3724         int i;
3725         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3726         char *vertexstring, *geometrystring, *fragmentstring;
3727         char permutationname[256];
3728         int vertstrings_count = 0;
3729         int geomstrings_count = 0;
3730         int fragstrings_count = 0;
3731         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3732         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3733         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3734
3735         if (p->compiled)
3736                 return;
3737         p->compiled = true;
3738         p->program = 0;
3739
3740         permutationname[0] = 0;
3741         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3742         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3743         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3744
3745         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3746
3747         // the first pretext is which type of shader to compile as
3748         // (later these will all be bound together as a program object)
3749         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3750         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3751         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3752
3753         // the second pretext is the mode (for example a light source)
3754         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3755         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3756         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3757         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3758
3759         // now add all the permutation pretexts
3760         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3761         {
3762                 if (permutation & (1<<i))
3763                 {
3764                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3765                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3766                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3767                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3768                 }
3769                 else
3770                 {
3771                         // keep line numbers correct
3772                         vertstrings_list[vertstrings_count++] = "\n";
3773                         geomstrings_list[geomstrings_count++] = "\n";
3774                         fragstrings_list[fragstrings_count++] = "\n";
3775                 }
3776         }
3777
3778         // add static parms
3779         R_CompileShader_AddStaticParms(mode, permutation);
3780         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3781         vertstrings_count += shaderstaticparms_count;
3782         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3783         geomstrings_count += shaderstaticparms_count;
3784         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3785         fragstrings_count += shaderstaticparms_count;
3786
3787         // now append the shader text itself
3788         vertstrings_list[vertstrings_count++] = vertexstring;
3789         geomstrings_list[geomstrings_count++] = geometrystring;
3790         fragstrings_list[fragstrings_count++] = fragmentstring;
3791
3792         // if any sources were NULL, clear the respective list
3793         if (!vertexstring)
3794                 vertstrings_count = 0;
3795         if (!geometrystring)
3796                 geomstrings_count = 0;
3797         if (!fragmentstring)
3798                 fragstrings_count = 0;
3799
3800         // compile the shader program
3801         if (vertstrings_count + geomstrings_count + fragstrings_count)
3802                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3803         if (p->program)
3804         {
3805                 CHECKGLERROR
3806                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3807                 // look up all the uniform variable names we care about, so we don't
3808                 // have to look them up every time we set them
3809
3810                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3811                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3812                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3813                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3814                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3815                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3816                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3817                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3818                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3819                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3820                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3821                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3822                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3823                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3824                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3825                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3826                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3827                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3828                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3829                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3830                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3831                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3832                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3833                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3834                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3835                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3836                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3837                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3838                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3839                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3840                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3841                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3842                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3843                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3844                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3845                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3846                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3847                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3848                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3849                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3850                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3851                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3852                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3853                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3854                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3855                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3856                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3857                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3858                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3859                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3860                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3861                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3862                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3863                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3864                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3865                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3866                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3867                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3868                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3869                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3870                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3871                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3872                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3873                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3874                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3875                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3876                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3877                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3878                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3879                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3880                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3881                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3882                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3883                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3884                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3885                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3886                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3887                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3888                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3889                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3890                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3891                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3892                 // initialize the samplers to refer to the texture units we use
3893                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3894                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3895                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3896                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3897                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3898                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3899                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3900                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3901                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3902                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3903                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3904                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3905                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3906                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3907                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3908                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3909                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3910                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3911                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3912                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3913                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3914                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3915                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3916                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3917                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3918                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3919                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3920                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3921                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3922                 CHECKGLERROR
3923                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3924         }
3925         else
3926                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3927
3928         // free the strings
3929         if (vertexstring)
3930                 Mem_Free(vertexstring);
3931         if (geometrystring)
3932                 Mem_Free(geometrystring);
3933         if (fragmentstring)
3934                 Mem_Free(fragmentstring);
3935 }
3936
3937 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3938 {
3939         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3940         if (r_glsl_permutation != perm)
3941         {
3942                 r_glsl_permutation = perm;
3943                 if (!r_glsl_permutation->program)
3944                 {
3945                         if (!r_glsl_permutation->compiled)
3946                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3947                         if (!r_glsl_permutation->program)
3948                         {
3949                                 // remove features until we find a valid permutation
3950                                 int i;
3951                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3952                                 {
3953                                         // reduce i more quickly whenever it would not remove any bits
3954                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3955                                         if (!(permutation & j))
3956                                                 continue;
3957                                         permutation -= j;
3958                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3959                                         if (!r_glsl_permutation->compiled)
3960                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3961                                         if (r_glsl_permutation->program)
3962                                                 break;
3963                                 }
3964                                 if (i >= SHADERPERMUTATION_COUNT)
3965                                 {
3966                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3967                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3968                                         qglUseProgramObjectARB(0);CHECKGLERROR
3969                                         return; // no bit left to clear, entire mode is broken
3970                                 }
3971                         }
3972                 }
3973                 CHECKGLERROR
3974                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3975         }
3976         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3977         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3978         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3979 }
3980
3981 #ifdef SUPPORTCG
3982 #include <Cg/cgGL.h>
3983 struct r_cg_permutation_s;
3984 typedef struct r_cg_permutation_s
3985 {
3986         /// hash lookup data
3987         struct r_cg_permutation_s *hashnext;
3988         unsigned int mode;
3989         unsigned int permutation;
3990
3991         /// indicates if we have tried compiling this permutation already
3992         qboolean compiled;
3993         /// 0 if compilation failed
3994         CGprogram vprogram;
3995         CGprogram fprogram;
3996         /// locations of detected parameters in programs, or NULL if not found
3997         CGparameter vp_EyePosition;
3998         CGparameter vp_FogPlane;
3999         CGparameter vp_LightDir;
4000         CGparameter vp_LightPosition;
4001         CGparameter vp_ModelToLight;
4002         CGparameter vp_TexMatrix;
4003         CGparameter vp_BackgroundTexMatrix;
4004         CGparameter vp_ModelViewProjectionMatrix;
4005         CGparameter vp_ModelViewMatrix;
4006         CGparameter vp_ShadowMapMatrix;
4007
4008         CGparameter fp_Texture_First;
4009         CGparameter fp_Texture_Second;
4010         CGparameter fp_Texture_GammaRamps;
4011         CGparameter fp_Texture_Normal;
4012         CGparameter fp_Texture_Color;
4013         CGparameter fp_Texture_Gloss;
4014         CGparameter fp_Texture_Glow;
4015         CGparameter fp_Texture_SecondaryNormal;
4016         CGparameter fp_Texture_SecondaryColor;
4017         CGparameter fp_Texture_SecondaryGloss;
4018         CGparameter fp_Texture_SecondaryGlow;
4019         CGparameter fp_Texture_Pants;
4020         CGparameter fp_Texture_Shirt;
4021         CGparameter fp_Texture_FogHeightTexture;
4022         CGparameter fp_Texture_FogMask;
4023         CGparameter fp_Texture_Lightmap;
4024         CGparameter fp_Texture_Deluxemap;
4025         CGparameter fp_Texture_Attenuation;
4026         CGparameter fp_Texture_Cube;
4027         CGparameter fp_Texture_Refraction;
4028         CGparameter fp_Texture_Reflection;
4029         CGparameter fp_Texture_ShadowMap2D;
4030         CGparameter fp_Texture_CubeProjection;
4031         CGparameter fp_Texture_ScreenDepth;
4032         CGparameter fp_Texture_ScreenNormalMap;
4033         CGparameter fp_Texture_ScreenDiffuse;
4034         CGparameter fp_Texture_ScreenSpecular;
4035         CGparameter fp_Texture_ReflectMask;
4036         CGparameter fp_Texture_ReflectCube;
4037         CGparameter fp_Alpha;
4038         CGparameter fp_BloomBlur_Parameters;
4039         CGparameter fp_ClientTime;
4040         CGparameter fp_Color_Ambient;
4041         CGparameter fp_Color_Diffuse;
4042         CGparameter fp_Color_Specular;
4043         CGparameter fp_Color_Glow;
4044         CGparameter fp_Color_Pants;
4045         CGparameter fp_Color_Shirt;
4046         CGparameter fp_DeferredColor_Ambient;
4047         CGparameter fp_DeferredColor_Diffuse;
4048         CGparameter fp_DeferredColor_Specular;
4049         CGparameter fp_DeferredMod_Diffuse;
4050         CGparameter fp_DeferredMod_Specular;
4051         CGparameter fp_DistortScaleRefractReflect;
4052         CGparameter fp_EyePosition;
4053         CGparameter fp_FogColor;
4054         CGparameter fp_FogHeightFade;
4055         CGparameter fp_FogPlane;
4056         CGparameter fp_FogPlaneViewDist;
4057         CGparameter fp_FogRangeRecip;
4058         CGparameter fp_LightColor;
4059         CGparameter fp_LightDir;
4060         CGparameter fp_LightPosition;
4061         CGparameter fp_OffsetMapping_Scale;
4062         CGparameter fp_PixelSize;
4063         CGparameter fp_ReflectColor;
4064         CGparameter fp_ReflectFactor;
4065         CGparameter fp_ReflectOffset;
4066         CGparameter fp_RefractColor;
4067         CGparameter fp_Saturation;
4068         CGparameter fp_ScreenCenterRefractReflect;
4069         CGparameter fp_ScreenScaleRefractReflect;
4070         CGparameter fp_ScreenToDepth;
4071         CGparameter fp_ShadowMap_Parameters;
4072         CGparameter fp_ShadowMap_TextureScale;
4073         CGparameter fp_SpecularPower;
4074         CGparameter fp_UserVec1;
4075         CGparameter fp_UserVec2;
4076         CGparameter fp_UserVec3;
4077         CGparameter fp_UserVec4;
4078         CGparameter fp_ViewTintColor;
4079         CGparameter fp_ViewToLight;
4080         CGparameter fp_PixelToScreenTexCoord;
4081         CGparameter fp_ModelToReflectCube;
4082         CGparameter fp_BloomColorSubtract;
4083         CGparameter fp_NormalmapScrollBlend;
4084 }
4085 r_cg_permutation_t;
4086
4087 /// information about each possible shader permutation
4088 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4089 /// currently selected permutation
4090 r_cg_permutation_t *r_cg_permutation;
4091 /// storage for permutations linked in the hash table
4092 memexpandablearray_t r_cg_permutationarray;
4093
4094 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
4095
4096 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4097 {
4098         //unsigned int hashdepth = 0;
4099         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4100         r_cg_permutation_t *p;
4101         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4102         {
4103                 if (p->mode == mode && p->permutation == permutation)
4104                 {
4105                         //if (hashdepth > 10)
4106                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4107                         return p;
4108                 }
4109                 //hashdepth++;
4110         }
4111         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4112         p->mode = mode;
4113         p->permutation = permutation;
4114         p->hashnext = r_cg_permutationhash[mode][hashindex];
4115         r_cg_permutationhash[mode][hashindex] = p;
4116         //if (hashdepth > 10)
4117         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4118         return p;
4119 }
4120
4121 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4122 {
4123         char *shaderstring;
4124         if (!filename || !filename[0])
4125                 return NULL;
4126         if (!strcmp(filename, "cg/default.cg"))
4127         {
4128                 if (!cgshaderstring)
4129                 {
4130                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4131                         if (cgshaderstring)
4132                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4133                         else
4134                                 cgshaderstring = (char *)builtincgshaderstring;
4135                 }
4136                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4137                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4138                 return shaderstring;
4139         }
4140         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4141         if (shaderstring)
4142         {
4143                 if (printfromdisknotice)
4144                         Con_DPrintf("from disk %s... ", filename);
4145                 return shaderstring;
4146         }
4147         return shaderstring;
4148 }
4149
4150 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4151 {
4152         // TODO: load or create .fp and .vp shader files
4153 }
4154
4155 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4156 {
4157         int i;
4158         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4159         int vertstring_length = 0;
4160         int geomstring_length = 0;
4161         int fragstring_length = 0;
4162         char *t;
4163         char *vertexstring, *geometrystring, *fragmentstring;
4164         char *vertstring, *geomstring, *fragstring;
4165         char permutationname[256];
4166         char cachename[256];
4167         CGprofile vertexProfile;
4168         CGprofile fragmentProfile;
4169         int vertstrings_count = 0;
4170         int geomstrings_count = 0;
4171         int fragstrings_count = 0;
4172         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4173         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4174         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4175
4176         if (p->compiled)
4177                 return;
4178         p->compiled = true;
4179         p->vprogram = NULL;
4180         p->fprogram = NULL;
4181
4182         permutationname[0] = 0;
4183         cachename[0] = 0;
4184         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4185         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4186         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4187
4188         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4189         strlcat(cachename, "cg/", sizeof(cachename));
4190
4191         // the first pretext is which type of shader to compile as
4192         // (later these will all be bound together as a program object)
4193         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4194         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4195         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4196
4197         // the second pretext is the mode (for example a light source)
4198         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4199         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4200         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4201         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4202         strlcat(cachename, modeinfo->name, sizeof(cachename));
4203
4204         // now add all the permutation pretexts
4205         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4206         {
4207                 if (permutation & (1<<i))
4208                 {
4209                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4210                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4211                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4212                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4213                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4214                 }
4215                 else
4216                 {
4217                         // keep line numbers correct
4218                         vertstrings_list[vertstrings_count++] = "\n";
4219                         geomstrings_list[geomstrings_count++] = "\n";
4220                         fragstrings_list[fragstrings_count++] = "\n";
4221                 }
4222         }
4223
4224         // add static parms
4225         R_CompileShader_AddStaticParms(mode, permutation);
4226         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4227         vertstrings_count += shaderstaticparms_count;
4228         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4229         geomstrings_count += shaderstaticparms_count;
4230         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4231         fragstrings_count += shaderstaticparms_count;
4232
4233         // replace spaces in the cachename with _ characters
4234         for (i = 0;cachename[i];i++)
4235                 if (cachename[i] == ' ')
4236                         cachename[i] = '_';
4237
4238         // now append the shader text itself
4239         vertstrings_list[vertstrings_count++] = vertexstring;
4240         geomstrings_list[geomstrings_count++] = geometrystring;
4241         fragstrings_list[fragstrings_count++] = fragmentstring;
4242
4243         // if any sources were NULL, clear the respective list
4244         if (!vertexstring)
4245                 vertstrings_count = 0;
4246         if (!geometrystring)
4247                 geomstrings_count = 0;
4248         if (!fragmentstring)
4249                 fragstrings_count = 0;
4250
4251         vertstring_length = 0;
4252         for (i = 0;i < vertstrings_count;i++)
4253                 vertstring_length += strlen(vertstrings_list[i]);
4254         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4255         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4256                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4257
4258         geomstring_length = 0;
4259         for (i = 0;i < geomstrings_count;i++)
4260                 geomstring_length += strlen(geomstrings_list[i]);
4261         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4262         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4263                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4264
4265         fragstring_length = 0;
4266         for (i = 0;i < fragstrings_count;i++)
4267                 fragstring_length += strlen(fragstrings_list[i]);
4268         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4269         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4270                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4271
4272         CHECKGLERROR
4273         CHECKCGERROR
4274         //vertexProfile = CG_PROFILE_ARBVP1;
4275         //fragmentProfile = CG_PROFILE_ARBFP1;
4276         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4277         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4278         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4279         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4280         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4281         CHECKGLERROR
4282
4283         // try to load the cached shader, or generate one
4284         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4285
4286         // if caching failed, do a dynamic compile for now
4287         CHECKCGERROR
4288         if (vertstring[0] && !p->vprogram)
4289                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4290         CHECKCGERROR
4291         if (fragstring[0] && !p->fprogram)
4292                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4293         CHECKCGERROR
4294
4295         // look up all the uniform variable names we care about, so we don't
4296         // have to look them up every time we set them
4297         if (p->vprogram)
4298         {
4299                 CHECKCGERROR
4300                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4301                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4302                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4303                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4304                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4305                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4306                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4307                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4308                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4309                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4310                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4311                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4312                 CHECKCGERROR
4313         }
4314         if (p->fprogram)
4315         {
4316                 CHECKCGERROR
4317                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4318                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4319                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4320                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4321                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4322                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4323                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4324                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4325                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4326                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4327                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4328                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4329                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4330                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4331                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4332                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4333                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4334                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4335                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4336                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4337                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4338                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4339                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4340                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4341                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4342                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4343                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4344                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4345                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4346                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4347                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4348                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4349                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4350                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4351                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4352                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4353                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4354                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4355                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4356                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4357                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4358                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4359                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4360                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4361                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4362                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4363                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4364                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4365                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4366                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4367                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4368                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4369                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4370                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4371                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4372                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4373                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4374                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4375                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4376                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4377                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4378                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4379                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4380                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4381                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4382                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4383                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4384                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4385                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4386                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4387                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4388                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4389                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4390                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4391                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4392                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4393                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4394                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4395                 CHECKCGERROR
4396         }
4397
4398         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4399                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4400         else
4401                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4402
4403         // free the strings
4404         if (vertstring)
4405                 Mem_Free(vertstring);
4406         if (geomstring)
4407                 Mem_Free(geomstring);
4408         if (fragstring)
4409                 Mem_Free(fragstring);
4410         if (vertexstring)
4411                 Mem_Free(vertexstring);
4412         if (geometrystring)
4413                 Mem_Free(geometrystring);
4414         if (fragmentstring)
4415                 Mem_Free(fragmentstring);
4416 }
4417
4418 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4419 {
4420         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4421         CHECKGLERROR
4422         CHECKCGERROR
4423         if (r_cg_permutation != perm)
4424         {
4425                 r_cg_permutation = perm;
4426                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4427                 {
4428                         if (!r_cg_permutation->compiled)
4429                                 R_CG_CompilePermutation(perm, mode, permutation);
4430                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4431                         {
4432                                 // remove features until we find a valid permutation
4433                                 int i;
4434                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4435                                 {
4436                                         // reduce i more quickly whenever it would not remove any bits
4437                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4438                                         if (!(permutation & j))
4439                                                 continue;
4440                                         permutation -= j;
4441                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4442                                         if (!r_cg_permutation->compiled)
4443                                                 R_CG_CompilePermutation(perm, mode, permutation);
4444                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4445                                                 break;
4446                                 }
4447                                 if (i >= SHADERPERMUTATION_COUNT)
4448                                 {
4449                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4450                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4451                                         return; // no bit left to clear, entire mode is broken
4452                                 }
4453                         }
4454                 }
4455                 CHECKGLERROR
4456                 CHECKCGERROR
4457                 if (r_cg_permutation->vprogram)
4458                 {
4459                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4460                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4461                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4462                 }
4463                 else
4464                 {
4465                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4466                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4467                 }
4468                 if (r_cg_permutation->fprogram)
4469                 {
4470                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4471                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4472                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4473                 }
4474                 else
4475                 {
4476                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4477                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4478                 }
4479         }
4480         CHECKCGERROR
4481         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4482         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4483         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4484 }
4485
4486 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4487 {
4488         cgGLSetTextureParameter(param, R_GetTexture(tex));
4489         cgGLEnableTextureParameter(param);
4490 }
4491 #endif
4492
4493 #ifdef SUPPORTD3D
4494
4495 #ifdef SUPPORTD3D
4496 #include <d3d9.h>
4497 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4498 extern D3DCAPS9 vid_d3d9caps;
4499 #endif
4500
4501 struct r_hlsl_permutation_s;
4502 typedef struct r_hlsl_permutation_s
4503 {
4504         /// hash lookup data
4505         struct r_hlsl_permutation_s *hashnext;
4506         unsigned int mode;
4507         unsigned int permutation;
4508
4509         /// indicates if we have tried compiling this permutation already
4510         qboolean compiled;
4511         /// NULL if compilation failed
4512         IDirect3DVertexShader9 *vertexshader;
4513         IDirect3DPixelShader9 *pixelshader;
4514 }
4515 r_hlsl_permutation_t;
4516
4517 typedef enum D3DVSREGISTER_e
4518 {
4519         D3DVSREGISTER_TexMatrix = 0, // float4x4
4520         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4521         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4522         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4523         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4524         D3DVSREGISTER_ModelToLight = 20, // float4x4
4525         D3DVSREGISTER_EyePosition = 24,
4526         D3DVSREGISTER_FogPlane = 25,
4527         D3DVSREGISTER_LightDir = 26,
4528         D3DVSREGISTER_LightPosition = 27,
4529 }
4530 D3DVSREGISTER_t;
4531
4532 typedef enum D3DPSREGISTER_e
4533 {
4534         D3DPSREGISTER_Alpha = 0,
4535         D3DPSREGISTER_BloomBlur_Parameters = 1,
4536         D3DPSREGISTER_ClientTime = 2,
4537         D3DPSREGISTER_Color_Ambient = 3,
4538         D3DPSREGISTER_Color_Diffuse = 4,
4539         D3DPSREGISTER_Color_Specular = 5,
4540         D3DPSREGISTER_Color_Glow = 6,
4541         D3DPSREGISTER_Color_Pants = 7,
4542         D3DPSREGISTER_Color_Shirt = 8,
4543         D3DPSREGISTER_DeferredColor_Ambient = 9,
4544         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4545         D3DPSREGISTER_DeferredColor_Specular = 11,
4546         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4547         D3DPSREGISTER_DeferredMod_Specular = 13,
4548         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4549         D3DPSREGISTER_EyePosition = 15, // unused
4550         D3DPSREGISTER_FogColor = 16,
4551         D3DPSREGISTER_FogHeightFade = 17,
4552         D3DPSREGISTER_FogPlane = 18,
4553         D3DPSREGISTER_FogPlaneViewDist = 19,
4554         D3DPSREGISTER_FogRangeRecip = 20,
4555         D3DPSREGISTER_LightColor = 21,
4556         D3DPSREGISTER_LightDir = 22, // unused
4557         D3DPSREGISTER_LightPosition = 23,
4558         D3DPSREGISTER_OffsetMapping_Scale = 24,
4559         D3DPSREGISTER_PixelSize = 25,
4560         D3DPSREGISTER_ReflectColor = 26,
4561         D3DPSREGISTER_ReflectFactor = 27,
4562         D3DPSREGISTER_ReflectOffset = 28,
4563         D3DPSREGISTER_RefractColor = 29,
4564         D3DPSREGISTER_Saturation = 30,
4565         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4566         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4567         D3DPSREGISTER_ScreenToDepth = 33,
4568         D3DPSREGISTER_ShadowMap_Parameters = 34,
4569         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4570         D3DPSREGISTER_SpecularPower = 36,
4571         D3DPSREGISTER_UserVec1 = 37,
4572         D3DPSREGISTER_UserVec2 = 38,
4573         D3DPSREGISTER_UserVec3 = 39,
4574         D3DPSREGISTER_UserVec4 = 40,
4575         D3DPSREGISTER_ViewTintColor = 41,
4576         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4577         D3DPSREGISTER_BloomColorSubtract = 43,
4578         D3DPSREGISTER_ViewToLight = 44, // float4x4
4579         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4580         D3DPSREGISTER_NormalmapScrollBlend = 52,
4581         // next at 53
4582 }
4583 D3DPSREGISTER_t;
4584
4585 /// information about each possible shader permutation
4586 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4587 /// currently selected permutation
4588 r_hlsl_permutation_t *r_hlsl_permutation;
4589 /// storage for permutations linked in the hash table
4590 memexpandablearray_t r_hlsl_permutationarray;
4591
4592 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4593 {
4594         //unsigned int hashdepth = 0;
4595         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4596         r_hlsl_permutation_t *p;
4597         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4598         {
4599                 if (p->mode == mode && p->permutation == permutation)
4600                 {
4601                         //if (hashdepth > 10)
4602                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4603                         return p;
4604                 }
4605                 //hashdepth++;
4606         }
4607         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4608         p->mode = mode;
4609         p->permutation = permutation;
4610         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4611         r_hlsl_permutationhash[mode][hashindex] = p;
4612         //if (hashdepth > 10)
4613         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4614         return p;
4615 }
4616
4617 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4618 {
4619         char *shaderstring;
4620         if (!filename || !filename[0])
4621                 return NULL;
4622         if (!strcmp(filename, "hlsl/default.hlsl"))
4623         {
4624                 if (!hlslshaderstring)
4625                 {
4626                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4627                         if (hlslshaderstring)
4628                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4629                         else
4630                                 hlslshaderstring = (char *)builtincgshaderstring;
4631                 }
4632                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4633                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4634                 return shaderstring;
4635         }
4636         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4637         if (shaderstring)
4638         {
4639                 if (printfromdisknotice)
4640                         Con_DPrintf("from disk %s... ", filename);
4641                 return shaderstring;
4642         }
4643         return shaderstring;
4644 }
4645
4646 #include <d3dx9.h>
4647 //#include <d3dx9shader.h>
4648 //#include <d3dx9mesh.h>
4649
4650 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4651 {
4652         DWORD *vsbin = NULL;
4653         DWORD *psbin = NULL;
4654         fs_offset_t vsbinsize;
4655         fs_offset_t psbinsize;
4656 //      IDirect3DVertexShader9 *vs = NULL;
4657 //      IDirect3DPixelShader9 *ps = NULL;
4658         ID3DXBuffer *vslog = NULL;
4659         ID3DXBuffer *vsbuffer = NULL;
4660         ID3DXConstantTable *vsconstanttable = NULL;
4661         ID3DXBuffer *pslog = NULL;
4662         ID3DXBuffer *psbuffer = NULL;
4663         ID3DXConstantTable *psconstanttable = NULL;
4664         int vsresult = 0;
4665         int psresult = 0;
4666         char temp[MAX_INPUTLINE];
4667         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4668         qboolean debugshader = gl_paranoid.integer != 0;
4669         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4670         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4671         if (!debugshader)
4672         {
4673                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4674                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4675         }
4676         if ((!vsbin && vertstring) || (!psbin && fragstring))
4677         {
4678                 const char* dllnames_d3dx9 [] =
4679                 {
4680                         "d3dx9_43.dll",
4681                         "d3dx9_42.dll",
4682                         "d3dx9_41.dll",
4683                         "d3dx9_40.dll",
4684                         "d3dx9_39.dll",
4685                         "d3dx9_38.dll",
4686                         "d3dx9_37.dll",
4687                         "d3dx9_36.dll",
4688                         "d3dx9_35.dll",
4689                         "d3dx9_34.dll",
4690                         "d3dx9_33.dll",
4691                         "d3dx9_32.dll",
4692                         "d3dx9_31.dll",
4693                         "d3dx9_30.dll",
4694                         "d3dx9_29.dll",
4695                         "d3dx9_28.dll",
4696                         "d3dx9_27.dll",
4697                         "d3dx9_26.dll",
4698                         "d3dx9_25.dll",
4699                         "d3dx9_24.dll",
4700                         NULL
4701                 };
4702                 dllhandle_t d3dx9_dll = NULL;
4703                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4704                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4705                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4706                 dllfunction_t d3dx9_dllfuncs[] =
4707                 {
4708                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4709                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4710                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4711                         {NULL, NULL}
4712                 };
4713                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4714                 {
4715                         DWORD shaderflags = 0;
4716                         if (debugshader)
4717                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4718                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4719                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4720                         if (vertstring && vertstring[0])
4721                         {
4722                                 if (debugshader)
4723                                 {
4724 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4725 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4726                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4727                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4728                                 }
4729                                 else
4730                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4731                                 if (vsbuffer)
4732                                 {
4733                                         vsbinsize = vsbuffer->GetBufferSize();
4734                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4735                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4736                                         vsbuffer->Release();
4737                                 }
4738                                 if (vslog)
4739                                 {
4740                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4741                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4742                                         vslog->Release();
4743                                 }
4744                         }
4745                         if (fragstring && fragstring[0])
4746                         {
4747                                 if (debugshader)
4748                                 {
4749 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4750 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4751                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4752                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4753                                 }
4754                                 else
4755                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4756                                 if (psbuffer)
4757                                 {
4758                                         psbinsize = psbuffer->GetBufferSize();
4759                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4760                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4761                                         psbuffer->Release();
4762                                 }
4763                                 if (pslog)
4764                                 {
4765                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4766                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4767                                         pslog->Release();
4768                                 }
4769                         }
4770                         Sys_UnloadLibrary(&d3dx9_dll);
4771                 }
4772                 else
4773                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4774         }
4775         if (vsbin && psbin)
4776         {
4777                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4778                 if (FAILED(vsresult))
4779                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4780                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4781                 if (FAILED(psresult))
4782                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4783         }
4784         // free the shader data
4785         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4786         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4787 }
4788
4789 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4790 {
4791         int i;
4792         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4793         int vertstring_length = 0;
4794         int geomstring_length = 0;
4795         int fragstring_length = 0;
4796         char *t;
4797         char *vertexstring, *geometrystring, *fragmentstring;
4798         char *vertstring, *geomstring, *fragstring;
4799         char permutationname[256];
4800         char cachename[256];
4801         int vertstrings_count = 0;
4802         int geomstrings_count = 0;
4803         int fragstrings_count = 0;
4804         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4805         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4806         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4807
4808         if (p->compiled)
4809                 return;
4810         p->compiled = true;
4811         p->vertexshader = NULL;
4812         p->pixelshader = NULL;
4813
4814         permutationname[0] = 0;
4815         cachename[0] = 0;
4816         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4817         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4818         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4819
4820         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4821         strlcat(cachename, "hlsl/", sizeof(cachename));
4822
4823         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4824         vertstrings_count = 0;
4825         geomstrings_count = 0;
4826         fragstrings_count = 0;
4827         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4828         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4829         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4830
4831         // the first pretext is which type of shader to compile as
4832         // (later these will all be bound together as a program object)
4833         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4834         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4835         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4836
4837         // the second pretext is the mode (for example a light source)
4838         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4839         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4840         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4841         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4842         strlcat(cachename, modeinfo->name, sizeof(cachename));
4843
4844         // now add all the permutation pretexts
4845         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4846         {
4847                 if (permutation & (1<<i))
4848                 {
4849                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4850                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4851                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4852                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4853                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4854                 }
4855                 else
4856                 {
4857                         // keep line numbers correct
4858                         vertstrings_list[vertstrings_count++] = "\n";
4859                         geomstrings_list[geomstrings_count++] = "\n";
4860                         fragstrings_list[fragstrings_count++] = "\n";
4861                 }
4862         }
4863
4864         // add static parms
4865         R_CompileShader_AddStaticParms(mode, permutation);
4866         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4867         vertstrings_count += shaderstaticparms_count;
4868         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4869         geomstrings_count += shaderstaticparms_count;
4870         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4871         fragstrings_count += shaderstaticparms_count;
4872
4873         // replace spaces in the cachename with _ characters
4874         for (i = 0;cachename[i];i++)
4875                 if (cachename[i] == ' ')
4876                         cachename[i] = '_';
4877
4878         // now append the shader text itself
4879         vertstrings_list[vertstrings_count++] = vertexstring;
4880         geomstrings_list[geomstrings_count++] = geometrystring;
4881         fragstrings_list[fragstrings_count++] = fragmentstring;
4882
4883         // if any sources were NULL, clear the respective list
4884         if (!vertexstring)
4885                 vertstrings_count = 0;
4886         if (!geometrystring)
4887                 geomstrings_count = 0;
4888         if (!fragmentstring)
4889                 fragstrings_count = 0;
4890
4891         vertstring_length = 0;
4892         for (i = 0;i < vertstrings_count;i++)
4893                 vertstring_length += strlen(vertstrings_list[i]);
4894         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4895         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4896                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4897
4898         geomstring_length = 0;
4899         for (i = 0;i < geomstrings_count;i++)
4900                 geomstring_length += strlen(geomstrings_list[i]);
4901         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4902         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4903                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4904
4905         fragstring_length = 0;
4906         for (i = 0;i < fragstrings_count;i++)
4907                 fragstring_length += strlen(fragstrings_list[i]);
4908         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4909         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4910                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4911
4912         // try to load the cached shader, or generate one
4913         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4914
4915         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4916                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4917         else
4918                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4919
4920         // free the strings
4921         if (vertstring)
4922                 Mem_Free(vertstring);
4923         if (geomstring)
4924                 Mem_Free(geomstring);
4925         if (fragstring)
4926                 Mem_Free(fragstring);
4927         if (vertexstring)
4928                 Mem_Free(vertexstring);
4929         if (geometrystring)
4930                 Mem_Free(geometrystring);
4931         if (fragmentstring)
4932                 Mem_Free(fragmentstring);
4933 }
4934
4935 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4936 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4937 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4938 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4939 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4940 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4941
4942 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4943 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4944 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4945 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4946 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4947 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4948
4949 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4950 {
4951         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4952         if (r_hlsl_permutation != perm)
4953         {
4954                 r_hlsl_permutation = perm;
4955                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4956                 {
4957                         if (!r_hlsl_permutation->compiled)
4958                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4959                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4960                         {
4961                                 // remove features until we find a valid permutation
4962                                 int i;
4963                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4964                                 {
4965                                         // reduce i more quickly whenever it would not remove any bits
4966                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4967                                         if (!(permutation & j))
4968                                                 continue;
4969                                         permutation -= j;
4970                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4971                                         if (!r_hlsl_permutation->compiled)
4972                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4973                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4974                                                 break;
4975                                 }
4976                                 if (i >= SHADERPERMUTATION_COUNT)
4977                                 {
4978                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4979                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4980                                         return; // no bit left to clear, entire mode is broken
4981                                 }
4982                         }
4983                 }
4984                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4985                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4986         }
4987         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4988         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4989         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4990 }
4991 #endif
4992
4993 void R_GLSL_Restart_f(void)
4994 {
4995         unsigned int i, limit;
4996         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4997                 Mem_Free(glslshaderstring);
4998         glslshaderstring = NULL;
4999         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
5000                 Mem_Free(cgshaderstring);
5001         cgshaderstring = NULL;
5002         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5003                 Mem_Free(hlslshaderstring);
5004         hlslshaderstring = NULL;
5005         switch(vid.renderpath)
5006         {
5007         case RENDERPATH_D3D9:
5008 #ifdef SUPPORTD3D
5009                 {
5010                         r_hlsl_permutation_t *p;
5011                         r_hlsl_permutation = NULL;
5012 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5013 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5014 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5015 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5016                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5017                         for (i = 0;i < limit;i++)
5018                         {
5019                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5020                                 {
5021                                         if (p->vertexshader)
5022                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5023                                         if (p->pixelshader)
5024                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5025                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5026                                 }
5027                         }
5028                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5029                 }
5030 #endif
5031                 break;
5032         case RENDERPATH_D3D10:
5033                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5034                 break;
5035         case RENDERPATH_D3D11:
5036                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5037                 break;
5038         case RENDERPATH_GL20:
5039                 {
5040                         r_glsl_permutation_t *p;
5041                         r_glsl_permutation = NULL;
5042                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5043                         for (i = 0;i < limit;i++)
5044                         {
5045                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5046                                 {
5047                                         GL_Backend_FreeProgram(p->program);
5048                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5049                                 }
5050                         }
5051                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5052                 }
5053                 break;
5054         case RENDERPATH_CGGL:
5055 #ifdef SUPPORTCG
5056                 {
5057                         r_cg_permutation_t *p;
5058                         r_cg_permutation = NULL;
5059                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5060                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5061                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5062                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5063                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5064                         for (i = 0;i < limit;i++)
5065                         {
5066                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5067                                 {
5068                                         if (p->vprogram)
5069                                                 cgDestroyProgram(p->vprogram);
5070                                         if (p->fprogram)
5071                                                 cgDestroyProgram(p->fprogram);
5072                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5073                                 }
5074                         }
5075                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5076                 }
5077 #endif
5078                 break;
5079         case RENDERPATH_GL13:
5080         case RENDERPATH_GL11:
5081                 break;
5082         }
5083 }
5084
5085 void R_GLSL_DumpShader_f(void)
5086 {
5087         int i;
5088         qfile_t *file;
5089
5090         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5091         if (file)
5092         {
5093                 FS_Print(file, "/* The engine may define the following macros:\n");
5094                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5095                 for (i = 0;i < SHADERMODE_COUNT;i++)
5096                         FS_Print(file, glslshadermodeinfo[i].pretext);
5097                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5098                         FS_Print(file, shaderpermutationinfo[i].pretext);
5099                 FS_Print(file, "*/\n");
5100                 FS_Print(file, builtinshaderstring);
5101                 FS_Close(file);
5102                 Con_Printf("glsl/default.glsl written\n");
5103         }
5104         else
5105                 Con_Printf("failed to write to glsl/default.glsl\n");
5106
5107 #ifdef SUPPORTCG
5108         file = FS_OpenRealFile("cg/default.cg", "w", false);
5109         if (file)
5110         {
5111                 FS_Print(file, "/* The engine may define the following macros:\n");
5112                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5113                 for (i = 0;i < SHADERMODE_COUNT;i++)
5114                         FS_Print(file, cgshadermodeinfo[i].pretext);
5115                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5116                         FS_Print(file, shaderpermutationinfo[i].pretext);
5117                 FS_Print(file, "*/\n");
5118                 FS_Print(file, builtincgshaderstring);
5119                 FS_Close(file);
5120                 Con_Printf("cg/default.cg written\n");
5121         }
5122         else
5123                 Con_Printf("failed to write to cg/default.cg\n");
5124 #endif
5125
5126 #ifdef SUPPORTD3D
5127         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5128         if (file)
5129         {
5130                 FS_Print(file, "/* The engine may define the following macros:\n");
5131                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5132                 for (i = 0;i < SHADERMODE_COUNT;i++)
5133                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5134                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5135                         FS_Print(file, shaderpermutationinfo[i].pretext);
5136                 FS_Print(file, "*/\n");
5137                 FS_Print(file, builtincgshaderstring);
5138                 FS_Close(file);
5139                 Con_Printf("hlsl/default.hlsl written\n");
5140         }
5141         else
5142                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5143 #endif
5144 }
5145
5146 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5147 {
5148         if (!second)
5149                 texturemode = GL_MODULATE;
5150         switch (vid.renderpath)
5151         {
5152         case RENDERPATH_D3D9:
5153 #ifdef SUPPORTD3D
5154                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5155                 R_Mesh_TexBind(GL20TU_FIRST , first );
5156                 R_Mesh_TexBind(GL20TU_SECOND, second);
5157 #endif
5158                 break;
5159         case RENDERPATH_D3D10:
5160                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5161                 break;
5162         case RENDERPATH_D3D11:
5163                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5164                 break;
5165         case RENDERPATH_GL20:
5166                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5167                 R_Mesh_TexBind(GL20TU_FIRST , first );
5168                 R_Mesh_TexBind(GL20TU_SECOND, second);
5169                 break;
5170         case RENDERPATH_CGGL:
5171 #ifdef SUPPORTCG
5172                 CHECKCGERROR
5173                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5174                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5175                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5176 #endif
5177                 break;
5178         case RENDERPATH_GL13:
5179                 R_Mesh_TexBind(0, first );
5180                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5181                 R_Mesh_TexBind(1, second);
5182                 if (second)
5183                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5184                 break;
5185         case RENDERPATH_GL11:
5186                 R_Mesh_TexBind(0, first );
5187                 break;
5188         }
5189 }
5190
5191 void R_SetupShader_DepthOrShadow(void)
5192 {
5193         switch (vid.renderpath)
5194         {
5195         case RENDERPATH_D3D9:
5196 #ifdef SUPPORTD3D
5197                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5198 #endif
5199                 break;
5200         case RENDERPATH_D3D10:
5201                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5202                 break;
5203         case RENDERPATH_D3D11:
5204                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5205                 break;
5206         case RENDERPATH_GL20:
5207                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5208                 break;
5209         case RENDERPATH_CGGL:
5210 #ifdef SUPPORTCG
5211                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5212 #endif
5213                 break;
5214         case RENDERPATH_GL13:
5215                 R_Mesh_TexBind(0, 0);
5216                 R_Mesh_TexBind(1, 0);
5217                 break;
5218         case RENDERPATH_GL11:
5219                 R_Mesh_TexBind(0, 0);
5220                 break;
5221         }
5222 }
5223
5224 void R_SetupShader_ShowDepth(void)
5225 {
5226         switch (vid.renderpath)
5227         {
5228         case RENDERPATH_D3D9:
5229 #ifdef SUPPORTHLSL
5230                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5231 #endif
5232                 break;
5233         case RENDERPATH_D3D10:
5234                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5235                 break;
5236         case RENDERPATH_D3D11:
5237                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5238                 break;
5239         case RENDERPATH_GL20:
5240                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5241                 break;
5242         case RENDERPATH_CGGL:
5243 #ifdef SUPPORTCG
5244                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5245 #endif
5246                 break;
5247         case RENDERPATH_GL13:
5248                 break;
5249         case RENDERPATH_GL11:
5250                 break;
5251         }
5252 }
5253
5254 extern qboolean r_shadow_usingdeferredprepass;
5255 extern cvar_t r_shadow_deferred_8bitrange;
5256 extern rtexture_t *r_shadow_attenuationgradienttexture;
5257 extern rtexture_t *r_shadow_attenuation2dtexture;
5258 extern rtexture_t *r_shadow_attenuation3dtexture;
5259 extern qboolean r_shadow_usingshadowmap2d;
5260 extern qboolean r_shadow_usingshadowmaportho;
5261 extern float r_shadow_shadowmap_texturescale[2];
5262 extern float r_shadow_shadowmap_parameters[4];
5263 extern qboolean r_shadow_shadowmapvsdct;
5264 extern qboolean r_shadow_shadowmapsampler;
5265 extern int r_shadow_shadowmappcf;
5266 extern rtexture_t *r_shadow_shadowmap2dtexture;
5267 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5268 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5269 extern matrix4x4_t r_shadow_shadowmapmatrix;
5270 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5271 extern int r_shadow_prepass_width;
5272 extern int r_shadow_prepass_height;
5273 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5274 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5275 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5276 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5277 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5278 extern cvar_t gl_mesh_separatearrays;
5279 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5280 {
5281         // a blendfunc allows colormod if:
5282         // a) it can never keep the destination pixel invariant, or
5283         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5284         // this is to prevent unintended side effects from colormod
5285
5286         // in formulas:
5287         // IF there is a (s, sa) for which for all (d, da),
5288         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5289         // THEN, for this (s, sa) and all (colormod, d, da):
5290         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5291         // OBVIOUSLY, this means that
5292         //   s*colormod * src(s*colormod, d, sa, da) = 0
5293         //   dst(s*colormod, d, sa, da)              = 1
5294
5295         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5296
5297         // main condition to leave dst color invariant:
5298         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5299         //   src == GL_ZERO:
5300         //     s * 0 + d * dst(s, d, sa, da) == d
5301         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5302         //       => colormod is a problem for GL_SRC_COLOR only
5303         //   src == GL_ONE:
5304         //     s + d * dst(s, d, sa, da) == d
5305         //       => s == 0
5306         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5307         //       => colormod is never problematic for these
5308         //   src == GL_SRC_COLOR:
5309         //     s*s + d * dst(s, d, sa, da) == d
5310         //       => s == 0
5311         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5312         //       => colormod is never problematic for these
5313         //   src == GL_ONE_MINUS_SRC_COLOR:
5314         //     s*(1-s) + d * dst(s, d, sa, da) == d
5315         //       => s == 0 or s == 1
5316         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5317         //       => colormod is a problem for GL_SRC_COLOR only
5318         //   src == GL_DST_COLOR
5319         //     s*d + d * dst(s, d, sa, da) == d
5320         //       => s == 1
5321         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5322         //       => colormod is always a problem
5323         //     or
5324         //       => s == 0
5325         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5326         //       => colormod is never problematic for these
5327         //       => BUT, we do not know s! We must assume it is problematic
5328         //       then... except in GL_ONE case, where we know all invariant
5329         //       cases are fine
5330         //   src == GL_ONE_MINUS_DST_COLOR
5331         //     s*(1-d) + d * dst(s, d, sa, da) == d
5332         //       => s == 0 (1-d is impossible to handle for our desired result)
5333         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5334         //       => colormod is never problematic for these
5335         //   src == GL_SRC_ALPHA
5336         //     s*sa + d * dst(s, d, sa, da) == d
5337         //       => s == 0, or sa == 0
5338         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5339         //       => colormod breaks in the case GL_SRC_COLOR only
5340         //   src == GL_ONE_MINUS_SRC_ALPHA
5341         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5342         //       => s == 0, or sa == 1
5343         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5344         //       => colormod breaks in the case GL_SRC_COLOR only
5345         //   src == GL_DST_ALPHA
5346         //     s*da + d * dst(s, d, sa, da) == d
5347         //       => s == 0
5348         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5349         //       => colormod is never problematic for these
5350
5351         switch(src)
5352         {
5353                 case GL_ZERO:
5354                 case GL_ONE_MINUS_SRC_COLOR:
5355                 case GL_SRC_ALPHA:
5356                 case GL_ONE_MINUS_SRC_ALPHA:
5357                         if(dst == GL_SRC_COLOR)
5358                                 return false;
5359                         return true;
5360                 case GL_ONE:
5361                 case GL_SRC_COLOR:
5362                 case GL_ONE_MINUS_DST_COLOR:
5363                 case GL_DST_ALPHA:
5364                 case GL_ONE_MINUS_DST_ALPHA:
5365                         return true;
5366                 case GL_DST_COLOR:
5367                         if(dst == GL_ONE)
5368                                 return true;
5369                         return false;
5370                 default:
5371                         return false;
5372         }
5373 }
5374 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
5375 {
5376         // select a permutation of the lighting shader appropriate to this
5377         // combination of texture, entity, light source, and fogging, only use the
5378         // minimum features necessary to avoid wasting rendering time in the
5379         // fragment shader on features that are not being used
5380         unsigned int permutation = 0;
5381         unsigned int mode = 0;
5382         qboolean allow_colormod;
5383         static float dummy_colormod[3] = {1, 1, 1};
5384         float *colormod = rsurface.colormod;
5385         float m16f[16];
5386         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5387         if (rsurfacepass == RSURFPASS_BACKGROUND)
5388         {
5389                 // distorted background
5390                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5391                 {
5392                         mode = SHADERMODE_WATER;
5393                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5394                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5395                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5396                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5397                 }
5398                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5399                 {
5400                         mode = SHADERMODE_REFRACTION;
5401                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5402                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5403                 }
5404                 else
5405                 {
5406                         mode = SHADERMODE_GENERIC;
5407                         permutation |= SHADERPERMUTATION_DIFFUSE;
5408                         GL_BlendFunc(GL_ONE, GL_ZERO);
5409                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5410                 }
5411                 GL_AlphaTest(false);
5412         }
5413         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5414         {
5415                 if (r_glsl_offsetmapping.integer)
5416                 {
5417                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5418                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5419                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5420                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5421                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5422                         {
5423                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5424                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5425                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5426                         }
5427                 }
5428                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5429                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5430                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5431                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5432                 // normalmap (deferred prepass), may use alpha test on diffuse
5433                 mode = SHADERMODE_DEFERREDGEOMETRY;
5434                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5435                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5436                 GL_AlphaTest(false);
5437                 GL_BlendFunc(GL_ONE, GL_ZERO);
5438                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5439         }
5440         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5441         {
5442                 if (r_glsl_offsetmapping.integer)
5443                 {
5444                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5445                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5446                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5447                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5448                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5449                         {
5450                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5451                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5452                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5453                         }
5454                 }
5455                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5456                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5457                 // light source
5458                 mode = SHADERMODE_LIGHTSOURCE;
5459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5460                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5461                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5462                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5463                 if (diffusescale > 0)
5464                         permutation |= SHADERPERMUTATION_DIFFUSE;
5465                 if (specularscale > 0)
5466                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5467                 if (r_refdef.fogenabled)
5468                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5469                 if (rsurface.texture->colormapping)
5470                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5471                 if (r_shadow_usingshadowmap2d)
5472                 {
5473                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5474                         if(r_shadow_shadowmapvsdct)
5475                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5476
5477                         if (r_shadow_shadowmapsampler)
5478                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5479                         if (r_shadow_shadowmappcf > 1)
5480                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5481                         else if (r_shadow_shadowmappcf)
5482                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5483                 }
5484                 if (rsurface.texture->reflectmasktexture)
5485                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5486                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5487                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5488                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5489         }
5490         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5491         {
5492                 if (r_glsl_offsetmapping.integer)
5493                 {
5494                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5495                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5496                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5497                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5498                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5499                         {
5500                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5501                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5502                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5503                         }
5504                 }
5505                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5506                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5507                 // unshaded geometry (fullbright or ambient model lighting)
5508                 mode = SHADERMODE_FLATCOLOR;
5509                 ambientscale = diffusescale = specularscale = 0;
5510                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5511                         permutation |= SHADERPERMUTATION_GLOW;
5512                 if (r_refdef.fogenabled)
5513                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5514                 if (rsurface.texture->colormapping)
5515                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5516                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5517                 {
5518                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5519                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5520
5521                         if (r_shadow_shadowmapsampler)
5522                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5523                         if (r_shadow_shadowmappcf > 1)
5524                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5525                         else if (r_shadow_shadowmappcf)
5526                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5527                 }
5528                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5529                         permutation |= SHADERPERMUTATION_REFLECTION;
5530                 if (rsurface.texture->reflectmasktexture)
5531                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5532                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5533                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5534                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5535         }
5536         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5537         {
5538                 if (r_glsl_offsetmapping.integer)
5539                 {
5540                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5541                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5542                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5543                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5544                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5545                         {
5546                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5547                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5548                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5549                         }
5550                 }
5551                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5552                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5553                 // directional model lighting
5554                 mode = SHADERMODE_LIGHTDIRECTION;
5555                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5556                         permutation |= SHADERPERMUTATION_GLOW;
5557                 permutation |= SHADERPERMUTATION_DIFFUSE;
5558                 if (specularscale > 0)
5559                         permutation |= SHADERPERMUTATION_SPECULAR;
5560                 if (r_refdef.fogenabled)
5561                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5562                 if (rsurface.texture->colormapping)
5563                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5564                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5565                 {
5566                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5567                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5568
5569                         if (r_shadow_shadowmapsampler)
5570                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5571                         if (r_shadow_shadowmappcf > 1)
5572                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5573                         else if (r_shadow_shadowmappcf)
5574                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5575                 }
5576                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5577                         permutation |= SHADERPERMUTATION_REFLECTION;
5578                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5579                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5580                 if (rsurface.texture->reflectmasktexture)
5581                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5582                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5583                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5584                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5585         }
5586         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5587         {
5588                 if (r_glsl_offsetmapping.integer)
5589                 {
5590                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5591                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5592                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5593                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5594                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5595                         {
5596                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5597                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5598                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5599                         }
5600                 }
5601                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5602                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5603                 // ambient model lighting
5604                 mode = SHADERMODE_LIGHTDIRECTION;
5605                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5606                         permutation |= SHADERPERMUTATION_GLOW;
5607                 if (r_refdef.fogenabled)
5608                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5609                 if (rsurface.texture->colormapping)
5610                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5611                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5612                 {
5613                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5614                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5615
5616                         if (r_shadow_shadowmapsampler)
5617                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5618                         if (r_shadow_shadowmappcf > 1)
5619                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5620                         else if (r_shadow_shadowmappcf)
5621                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5622                 }
5623                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5624                         permutation |= SHADERPERMUTATION_REFLECTION;
5625                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5626                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5627                 if (rsurface.texture->reflectmasktexture)
5628                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5629                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5630                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5631                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5632         }
5633         else
5634         {
5635                 if (r_glsl_offsetmapping.integer)
5636                 {
5637                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5638                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5639                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5640                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5641                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5642                         {
5643                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5644                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5645                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5646                         }
5647                 }
5648                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5649                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5650                 // lightmapped wall
5651                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5652                         permutation |= SHADERPERMUTATION_GLOW;
5653                 if (r_refdef.fogenabled)
5654                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5655                 if (rsurface.texture->colormapping)
5656                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5657                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5658                 {
5659                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5660                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5661
5662                         if (r_shadow_shadowmapsampler)
5663                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5664                         if (r_shadow_shadowmappcf > 1)
5665                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5666                         else if (r_shadow_shadowmappcf)
5667                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5668                 }
5669                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5670                         permutation |= SHADERPERMUTATION_REFLECTION;
5671                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5672                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5673                 if (rsurface.texture->reflectmasktexture)
5674                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5675                 if (FAKELIGHT_ENABLED)
5676                 {
5677                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5678                         mode = SHADERMODE_FAKELIGHT;
5679                         permutation |= SHADERPERMUTATION_DIFFUSE;
5680                         if (specularscale > 0)
5681                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5682                 }
5683                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5684                 {
5685                         // deluxemapping (light direction texture)
5686                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5687                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5688                         else
5689                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5690                         permutation |= SHADERPERMUTATION_DIFFUSE;
5691                         if (specularscale > 0)
5692                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5693                 }
5694                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5695                 {
5696                         // fake deluxemapping (uniform light direction in tangentspace)
5697                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5698                         permutation |= SHADERPERMUTATION_DIFFUSE;
5699                         if (specularscale > 0)
5700                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5701                 }
5702                 else if (rsurface.uselightmaptexture)
5703                 {
5704                         // ordinary lightmapping (q1bsp, q3bsp)
5705                         mode = SHADERMODE_LIGHTMAP;
5706                 }
5707                 else
5708                 {
5709                         // ordinary vertex coloring (q3bsp)
5710                         mode = SHADERMODE_VERTEXCOLOR;
5711                 }
5712                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5713                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5714                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5715         }
5716         if(!allow_colormod)
5717                 colormod = dummy_colormod;
5718         switch(vid.renderpath)
5719         {
5720         case RENDERPATH_D3D9:
5721 #ifdef SUPPORTD3D
5722                 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);
5723                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5724                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5725                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5726                 if (mode == SHADERMODE_LIGHTSOURCE)
5727                 {
5728                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5729                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5730                 }
5731                 else
5732                 {
5733                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5734                         {
5735                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5736                         }
5737                 }
5738                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5739                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5740                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5741                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5742                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5743
5744                 if (mode == SHADERMODE_LIGHTSOURCE)
5745                 {
5746                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5747                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5748                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5749                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5750                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5751
5752                         // additive passes are only darkened by fog, not tinted
5753                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5754                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5755                 }
5756                 else
5757                 {
5758                         if (mode == SHADERMODE_FLATCOLOR)
5759                         {
5760                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5761                         }
5762                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5763                         {
5764                                 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]);
5765                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5766                                 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);
5767                                 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);
5768                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5769                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5770                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5771                         }
5772                         else
5773                         {
5774                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5775                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5776                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5777                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5778                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5779                         }
5780                         // additive passes are only darkened by fog, not tinted
5781                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5782                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5783                         else
5784                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5785                         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);
5786                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5787                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5788                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5789                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5790                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5791                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5792                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5793                         if (mode == SHADERMODE_WATER)
5794                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5795                 }
5796                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5797                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5798                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5799                 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));
5800                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5801                 if (rsurface.texture->pantstexture)
5802                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5803                 else
5804                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5805                 if (rsurface.texture->shirttexture)
5806                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5807                 else
5808                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5809                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5810                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5811                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5812                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5813                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5814                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5815                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5816
5817                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5818                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5819                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5820                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5821                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5822                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5823                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5824                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5825                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5826                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5827                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5828                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5829                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5830                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5831                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5832                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5833                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5834                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5835                 {
5836                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5837                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5838                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5839                 }
5840                 else
5841                 {
5842                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5843                 }
5844 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5845 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5846                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5847                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5848                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5849                 {
5850                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5851                         if (rsurface.rtlight)
5852                         {
5853                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5854                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5855                         }
5856                 }
5857 #endif
5858                 break;
5859         case RENDERPATH_D3D10:
5860                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5861                 break;
5862         case RENDERPATH_D3D11:
5863                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5864                 break;
5865         case RENDERPATH_GL20:
5866                 if (gl_mesh_separatearrays.integer)
5867                 {
5868                         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);
5869                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5870                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5871                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5872                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5873                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5874                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5875                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5876                 }
5877                 else
5878                 {
5879                         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);
5880                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5881                 }
5882                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5883                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5884                 if (mode == SHADERMODE_LIGHTSOURCE)
5885                 {
5886                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5887                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5888                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5889                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5890                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5891                         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);
5892         
5893                         // additive passes are only darkened by fog, not tinted
5894                         if (r_glsl_permutation->loc_FogColor >= 0)
5895                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5896                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5897                 }
5898                 else
5899                 {
5900                         if (mode == SHADERMODE_FLATCOLOR)
5901                         {
5902                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5903                         }
5904                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5905                         {
5906                                 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]);
5907                                 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]);
5908                                 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);
5909                                 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);
5910                                 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);
5911                                 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]);
5912                                 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]);
5913                         }
5914                         else
5915                         {
5916                                 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]);
5917                                 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]);
5918                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5919                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5920                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5921                         }
5922                         // additive passes are only darkened by fog, not tinted
5923                         if (r_glsl_permutation->loc_FogColor >= 0)
5924                         {
5925                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5926                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5927                                 else
5928                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5929                         }
5930                         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);
5931                         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]);
5932                         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]);
5933                         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]);
5934                         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]);
5935                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5936                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5937                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5938                         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]);
5939                 }
5940                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5941                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5942                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5943                 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]);
5944                 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]);
5945
5946                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5947                 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));
5948                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5949                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5950                 {
5951                         if (rsurface.texture->pantstexture)
5952                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5953                         else
5954                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5955                 }
5956                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5957                 {
5958                         if (rsurface.texture->shirttexture)
5959                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5960                         else
5961                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5962                 }
5963                 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]);
5964                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5965                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5966                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5967                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5968                 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]);
5969                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5970
5971         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5972         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5973         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5974                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5975                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5976                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5977                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5978                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5979                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5980                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5981                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5982                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5983                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5984                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5985                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5986                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5987                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5988                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5989                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5990                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5991                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5992                 {
5993                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5994                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5995                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5996                 }
5997                 else
5998                 {
5999                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6000                 }
6001 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6002 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6003                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6004                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6005                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6006                 {
6007                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6008                         if (rsurface.rtlight)
6009                         {
6010                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6011                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6012                         }
6013                 }
6014                 CHECKGLERROR
6015                 break;
6016         case RENDERPATH_CGGL:
6017 #ifdef SUPPORTCG
6018                 if (gl_mesh_separatearrays.integer)
6019                 {
6020                         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);
6021                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6022                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6023                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6024                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6025                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6026                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6027                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6028                 }
6029                 else
6030                 {
6031                         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);
6032                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6033                 }
6034                 R_SetupShader_SetPermutationCG(mode, permutation);
6035                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6036                 if (mode == SHADERMODE_LIGHTSOURCE)
6037                 {
6038                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6039                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6040                 }
6041                 else
6042                 {
6043                         if (mode == SHADERMODE_LIGHTDIRECTION)
6044                         {
6045                                 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
6046                         }
6047                 }
6048                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6049                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6050                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6051                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6052                 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
6053                 CHECKGLERROR
6054
6055                 if (mode == SHADERMODE_LIGHTSOURCE)
6056                 {
6057                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6058                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6059                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6060                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6061                         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
6062
6063                         // additive passes are only darkened by fog, not tinted
6064                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6065                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6066                 }
6067                 else
6068                 {
6069                         if (mode == SHADERMODE_FLATCOLOR)
6070                         {
6071                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6072                         }
6073                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6074                         {
6075                                 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
6076                                 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
6077                                 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
6078                                 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
6079                                 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
6080                                 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
6081                                 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
6082                         }
6083                         else
6084                         {
6085                                 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
6086                                 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
6087                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6088                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6089                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6090                         }
6091                         // additive passes are only darkened by fog, not tinted
6092                         if (r_cg_permutation->fp_FogColor)
6093                         {
6094                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6095                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6096                                 else
6097                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6098                                 CHECKCGERROR
6099                         }
6100                         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
6101                         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
6102                         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
6103                         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
6104                         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
6105                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6106                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6107                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6108                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6109                 }
6110                 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
6111                 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
6112                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6113                 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
6114                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6115                 if (r_cg_permutation->fp_Color_Pants)
6116                 {
6117                         if (rsurface.texture->pantstexture)
6118                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6119                         else
6120                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6121                         CHECKCGERROR
6122                 }
6123                 if (r_cg_permutation->fp_Color_Shirt)
6124                 {
6125                         if (rsurface.texture->shirttexture)
6126                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6127                         else
6128                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6129                         CHECKCGERROR
6130                 }
6131                 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
6132                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6133                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6134                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6135                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6136                 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
6137                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6138
6139         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6140         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6141         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6142                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6143                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6144                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6145                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6146                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6147                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6148                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6149                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6150                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6151                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6152                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6153                 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
6154                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6155                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6156                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6157                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6158                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6159                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6160                 {
6161                         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
6162                         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
6163                         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
6164                 }
6165                 else
6166                 {
6167                         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
6168                 }
6169                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6170                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6171                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6172                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6173                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6174                 {
6175                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6176                         if (rsurface.rtlight)
6177                         {
6178                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6179                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6180                         }
6181                 }
6182
6183                 CHECKGLERROR
6184 #endif
6185                 break;
6186         case RENDERPATH_GL13:
6187         case RENDERPATH_GL11:
6188                 break;
6189         }
6190 }
6191
6192 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6193 {
6194         // select a permutation of the lighting shader appropriate to this
6195         // combination of texture, entity, light source, and fogging, only use the
6196         // minimum features necessary to avoid wasting rendering time in the
6197         // fragment shader on features that are not being used
6198         unsigned int permutation = 0;
6199         unsigned int mode = 0;
6200         const float *lightcolorbase = rtlight->currentcolor;
6201         float ambientscale = rtlight->ambientscale;
6202         float diffusescale = rtlight->diffusescale;
6203         float specularscale = rtlight->specularscale;
6204         // this is the location of the light in view space
6205         vec3_t viewlightorigin;
6206         // this transforms from view space (camera) to light space (cubemap)
6207         matrix4x4_t viewtolight;
6208         matrix4x4_t lighttoview;
6209         float viewtolight16f[16];
6210         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6211         // light source
6212         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6213         if (rtlight->currentcubemap != r_texture_whitecube)
6214                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6215         if (diffusescale > 0)
6216                 permutation |= SHADERPERMUTATION_DIFFUSE;
6217         if (specularscale > 0)
6218                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6219         if (r_shadow_usingshadowmap2d)
6220         {
6221                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6222                 if (r_shadow_shadowmapvsdct)
6223                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6224
6225                 if (r_shadow_shadowmapsampler)
6226                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6227                 if (r_shadow_shadowmappcf > 1)
6228                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6229                 else if (r_shadow_shadowmappcf)
6230                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6231         }
6232         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6233         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6234         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6235         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6236         switch(vid.renderpath)
6237         {
6238         case RENDERPATH_D3D9:
6239 #ifdef SUPPORTD3D
6240                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6241                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6242                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6243                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6244                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6245                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6246                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6247                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6248                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6249                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6250                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6251
6252                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6253                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6254                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6255                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6256                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6257                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6258 #endif
6259                 break;
6260         case RENDERPATH_D3D10:
6261                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6262                 break;
6263         case RENDERPATH_D3D11:
6264                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6265                 break;
6266         case RENDERPATH_GL20:
6267                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6268                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6269                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6270                 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);
6271                 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);
6272                 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);
6273                 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]);
6274                 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]);
6275                 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));
6276                 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]);
6277                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6278
6279                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6280                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6281                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6282                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6283                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6284                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6285                 break;
6286         case RENDERPATH_CGGL:
6287 #ifdef SUPPORTCG
6288                 R_SetupShader_SetPermutationCG(mode, permutation);
6289                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6290                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6291                 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
6292                 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
6293                 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
6294                 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
6295                 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
6296                 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
6297                 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
6298                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6299
6300                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6301                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6302                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6303                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6304                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6305                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6306 #endif
6307                 break;
6308         case RENDERPATH_GL13:
6309         case RENDERPATH_GL11:
6310                 break;
6311         }
6312 }
6313
6314 #define SKINFRAME_HASH 1024
6315
6316 typedef struct
6317 {
6318         int loadsequence; // incremented each level change
6319         memexpandablearray_t array;
6320         skinframe_t *hash[SKINFRAME_HASH];
6321 }
6322 r_skinframe_t;
6323 r_skinframe_t r_skinframe;
6324
6325 void R_SkinFrame_PrepareForPurge(void)
6326 {
6327         r_skinframe.loadsequence++;
6328         // wrap it without hitting zero
6329         if (r_skinframe.loadsequence >= 200)
6330                 r_skinframe.loadsequence = 1;
6331 }
6332
6333 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6334 {
6335         if (!skinframe)
6336                 return;
6337         // mark the skinframe as used for the purging code
6338         skinframe->loadsequence = r_skinframe.loadsequence;
6339 }
6340
6341 void R_SkinFrame_Purge(void)
6342 {
6343         int i;
6344         skinframe_t *s;
6345         for (i = 0;i < SKINFRAME_HASH;i++)
6346         {
6347                 for (s = r_skinframe.hash[i];s;s = s->next)
6348                 {
6349                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6350                         {
6351                                 if (s->merged == s->base)
6352                                         s->merged = NULL;
6353                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6354                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6355                                 R_PurgeTexture(s->merged);s->merged = NULL;
6356                                 R_PurgeTexture(s->base  );s->base   = NULL;
6357                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6358                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6359                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6360                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6361                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6362                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6363                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6364                                 s->loadsequence = 0;
6365                         }
6366                 }
6367         }
6368 }
6369
6370 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6371         skinframe_t *item;
6372         char basename[MAX_QPATH];
6373
6374         Image_StripImageExtension(name, basename, sizeof(basename));
6375
6376         if( last == NULL ) {
6377                 int hashindex;
6378                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6379                 item = r_skinframe.hash[hashindex];
6380         } else {
6381                 item = last->next;
6382         }
6383
6384         // linearly search through the hash bucket
6385         for( ; item ; item = item->next ) {
6386                 if( !strcmp( item->basename, basename ) ) {
6387                         return item;
6388                 }
6389         }
6390         return NULL;
6391 }
6392
6393 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6394 {
6395         skinframe_t *item;
6396         int hashindex;
6397         char basename[MAX_QPATH];
6398
6399         Image_StripImageExtension(name, basename, sizeof(basename));
6400
6401         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6402         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6403                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6404                         break;
6405
6406         if (!item) {
6407                 rtexture_t *dyntexture;
6408                 // check whether its a dynamic texture
6409                 dyntexture = CL_GetDynTexture( basename );
6410                 if (!add && !dyntexture)
6411                         return NULL;
6412                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6413                 memset(item, 0, sizeof(*item));
6414                 strlcpy(item->basename, basename, sizeof(item->basename));
6415                 item->base = dyntexture; // either NULL or dyntexture handle
6416                 item->textureflags = textureflags;
6417                 item->comparewidth = comparewidth;
6418                 item->compareheight = compareheight;
6419                 item->comparecrc = comparecrc;
6420                 item->next = r_skinframe.hash[hashindex];
6421                 r_skinframe.hash[hashindex] = item;
6422         }
6423         else if( item->base == NULL )
6424         {
6425                 rtexture_t *dyntexture;
6426                 // check whether its a dynamic texture
6427                 // 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]
6428                 dyntexture = CL_GetDynTexture( basename );
6429                 item->base = dyntexture; // either NULL or dyntexture handle
6430         }
6431
6432         R_SkinFrame_MarkUsed(item);
6433         return item;
6434 }
6435
6436 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6437         { \
6438                 unsigned long long avgcolor[5], wsum; \
6439                 int pix, comp, w; \
6440                 avgcolor[0] = 0; \
6441                 avgcolor[1] = 0; \
6442                 avgcolor[2] = 0; \
6443                 avgcolor[3] = 0; \
6444                 avgcolor[4] = 0; \
6445                 wsum = 0; \
6446                 for(pix = 0; pix < cnt; ++pix) \
6447                 { \
6448                         w = 0; \
6449                         for(comp = 0; comp < 3; ++comp) \
6450                                 w += getpixel; \
6451                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6452                         { \
6453                                 ++wsum; \
6454                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6455                                 w = getpixel; \
6456                                 for(comp = 0; comp < 3; ++comp) \
6457                                         avgcolor[comp] += getpixel * w; \
6458                                 avgcolor[3] += w; \
6459                         } \
6460                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6461                         avgcolor[4] += getpixel; \
6462                 } \
6463                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6464                         avgcolor[3] = 1; \
6465                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6466                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6467                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6468                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6469         }
6470
6471 extern cvar_t gl_picmip;
6472 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6473 {
6474         int j;
6475         unsigned char *pixels;
6476         unsigned char *bumppixels;
6477         unsigned char *basepixels = NULL;
6478         int basepixels_width = 0;
6479         int basepixels_height = 0;
6480         skinframe_t *skinframe;
6481         rtexture_t *ddsbase = NULL;
6482         qboolean ddshasalpha = false;
6483         float ddsavgcolor[4];
6484         char basename[MAX_QPATH];
6485         int miplevel = R_PicmipForFlags(textureflags);
6486         int savemiplevel = miplevel;
6487         int mymiplevel;
6488
6489         if (cls.state == ca_dedicated)
6490                 return NULL;
6491
6492         // return an existing skinframe if already loaded
6493         // if loading of the first image fails, don't make a new skinframe as it
6494         // would cause all future lookups of this to be missing
6495         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6496         if (skinframe && skinframe->base)
6497                 return skinframe;
6498
6499         Image_StripImageExtension(name, basename, sizeof(basename));
6500
6501         // check for DDS texture file first
6502         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6503         {
6504                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6505                 if (basepixels == NULL)
6506                         return NULL;
6507         }
6508
6509         // FIXME handle miplevel
6510
6511         if (developer_loading.integer)
6512                 Con_Printf("loading skin \"%s\"\n", name);
6513
6514         // we've got some pixels to store, so really allocate this new texture now
6515         if (!skinframe)
6516                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6517         skinframe->stain = NULL;
6518         skinframe->merged = NULL;
6519         skinframe->base = NULL;
6520         skinframe->pants = NULL;
6521         skinframe->shirt = NULL;
6522         skinframe->nmap = NULL;
6523         skinframe->gloss = NULL;
6524         skinframe->glow = NULL;
6525         skinframe->fog = NULL;
6526         skinframe->reflect = NULL;
6527         skinframe->hasalpha = false;
6528
6529         if (ddsbase)
6530         {
6531                 skinframe->base = ddsbase;
6532                 skinframe->hasalpha = ddshasalpha;
6533                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6534                 if (r_loadfog && skinframe->hasalpha)
6535                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6536                 //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]);
6537         }
6538         else
6539         {
6540                 basepixels_width = image_width;
6541                 basepixels_height = image_height;
6542                 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);
6543                 if (textureflags & TEXF_ALPHA)
6544                 {
6545                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6546                         {
6547                                 if (basepixels[j] < 255)
6548                                 {
6549                                         skinframe->hasalpha = true;
6550                                         break;
6551                                 }
6552                         }
6553                         if (r_loadfog && skinframe->hasalpha)
6554                         {
6555                                 // has transparent pixels
6556                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6557                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6558                                 {
6559                                         pixels[j+0] = 255;
6560                                         pixels[j+1] = 255;
6561                                         pixels[j+2] = 255;
6562                                         pixels[j+3] = basepixels[j+3];
6563                                 }
6564                                 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);
6565                                 Mem_Free(pixels);
6566                         }
6567                 }
6568                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6569                 //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]);
6570                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6571                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6572                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6573                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6574         }
6575
6576         if (r_loaddds)
6577         {
6578                 mymiplevel = savemiplevel;
6579                 if (r_loadnormalmap)
6580                         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);
6581                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6582                 if (r_loadgloss)
6583                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6584                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6585                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6586                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6587         }
6588
6589         // _norm is the name used by tenebrae and has been adopted as standard
6590         if (r_loadnormalmap && skinframe->nmap == NULL)
6591         {
6592                 mymiplevel = savemiplevel;
6593                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6594                 {
6595                         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);
6596                         Mem_Free(pixels);
6597                         pixels = NULL;
6598                 }
6599                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6600                 {
6601                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6602                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6603                         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);
6604                         Mem_Free(pixels);
6605                         Mem_Free(bumppixels);
6606                 }
6607                 else if (r_shadow_bumpscale_basetexture.value > 0)
6608                 {
6609                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6610                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6611                         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);
6612                         Mem_Free(pixels);
6613                 }
6614                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6615                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6616         }
6617
6618         // _luma is supported only for tenebrae compatibility
6619         // _glow is the preferred name
6620         mymiplevel = savemiplevel;
6621         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))))
6622         {
6623                 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);
6624                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6625                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6626                 Mem_Free(pixels);pixels = NULL;
6627         }
6628
6629         mymiplevel = savemiplevel;
6630         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6631         {
6632                 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);
6633                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6634                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6635                 Mem_Free(pixels);
6636                 pixels = NULL;
6637         }
6638
6639         mymiplevel = savemiplevel;
6640         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6641         {
6642                 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);
6643                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6644                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6645                 Mem_Free(pixels);
6646                 pixels = NULL;
6647         }
6648
6649         mymiplevel = savemiplevel;
6650         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6651         {
6652                 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);
6653                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6654                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6655                 Mem_Free(pixels);
6656                 pixels = NULL;
6657         }
6658
6659         mymiplevel = savemiplevel;
6660         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6661         {
6662                 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);
6663                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6664                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6665                 Mem_Free(pixels);
6666                 pixels = NULL;
6667         }
6668
6669         if (basepixels)
6670                 Mem_Free(basepixels);
6671
6672         return skinframe;
6673 }
6674
6675 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6676 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6677 {
6678         int i;
6679         unsigned char *temp1, *temp2;
6680         skinframe_t *skinframe;
6681
6682         if (cls.state == ca_dedicated)
6683                 return NULL;
6684
6685         // if already loaded just return it, otherwise make a new skinframe
6686         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6687         if (skinframe && skinframe->base)
6688                 return skinframe;
6689
6690         skinframe->stain = NULL;
6691         skinframe->merged = NULL;
6692         skinframe->base = NULL;
6693         skinframe->pants = NULL;
6694         skinframe->shirt = NULL;
6695         skinframe->nmap = NULL;
6696         skinframe->gloss = NULL;
6697         skinframe->glow = NULL;
6698         skinframe->fog = NULL;
6699         skinframe->reflect = NULL;
6700         skinframe->hasalpha = false;
6701
6702         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6703         if (!skindata)
6704                 return NULL;
6705
6706         if (developer_loading.integer)
6707                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6708
6709         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6710         {
6711                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6712                 temp2 = temp1 + width * height * 4;
6713                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6714                 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);
6715                 Mem_Free(temp1);
6716         }
6717         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6718         if (textureflags & TEXF_ALPHA)
6719         {
6720                 for (i = 3;i < width * height * 4;i += 4)
6721                 {
6722                         if (skindata[i] < 255)
6723                         {
6724                                 skinframe->hasalpha = true;
6725                                 break;
6726                         }
6727                 }
6728                 if (r_loadfog && skinframe->hasalpha)
6729                 {
6730                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6731                         memcpy(fogpixels, skindata, width * height * 4);
6732                         for (i = 0;i < width * height * 4;i += 4)
6733                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6734                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6735                         Mem_Free(fogpixels);
6736                 }
6737         }
6738
6739         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6740         //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]);
6741
6742         return skinframe;
6743 }
6744
6745 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6746 {
6747         int i;
6748         int featuresmask;
6749         skinframe_t *skinframe;
6750
6751         if (cls.state == ca_dedicated)
6752                 return NULL;
6753
6754         // if already loaded just return it, otherwise make a new skinframe
6755         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6756         if (skinframe && skinframe->base)
6757                 return skinframe;
6758
6759         skinframe->stain = NULL;
6760         skinframe->merged = NULL;
6761         skinframe->base = NULL;
6762         skinframe->pants = NULL;
6763         skinframe->shirt = NULL;
6764         skinframe->nmap = NULL;
6765         skinframe->gloss = NULL;
6766         skinframe->glow = NULL;
6767         skinframe->fog = NULL;
6768         skinframe->reflect = NULL;
6769         skinframe->hasalpha = false;
6770
6771         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6772         if (!skindata)
6773                 return NULL;
6774
6775         if (developer_loading.integer)
6776                 Con_Printf("loading quake skin \"%s\"\n", name);
6777
6778         // 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)
6779         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6780         memcpy(skinframe->qpixels, skindata, width*height);
6781         skinframe->qwidth = width;
6782         skinframe->qheight = height;
6783
6784         featuresmask = 0;
6785         for (i = 0;i < width * height;i++)
6786                 featuresmask |= palette_featureflags[skindata[i]];
6787
6788         skinframe->hasalpha = false;
6789         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6790         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6791         skinframe->qgeneratemerged = true;
6792         skinframe->qgeneratebase = skinframe->qhascolormapping;
6793         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6794
6795         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6796         //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]);
6797
6798         return skinframe;
6799 }
6800
6801 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6802 {
6803         int width;
6804         int height;
6805         unsigned char *skindata;
6806
6807         if (!skinframe->qpixels)
6808                 return;
6809
6810         if (!skinframe->qhascolormapping)
6811                 colormapped = false;
6812
6813         if (colormapped)
6814         {
6815                 if (!skinframe->qgeneratebase)
6816                         return;
6817         }
6818         else
6819         {
6820                 if (!skinframe->qgeneratemerged)
6821                         return;
6822         }
6823
6824         width = skinframe->qwidth;
6825         height = skinframe->qheight;
6826         skindata = skinframe->qpixels;
6827
6828         if (skinframe->qgeneratenmap)
6829         {
6830                 unsigned char *temp1, *temp2;
6831                 skinframe->qgeneratenmap = false;
6832                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6833                 temp2 = temp1 + width * height * 4;
6834                 // use either a custom palette or the quake palette
6835                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6836                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6837                 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);
6838                 Mem_Free(temp1);
6839         }
6840
6841         if (skinframe->qgenerateglow)
6842         {
6843                 skinframe->qgenerateglow = false;
6844                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6845         }
6846
6847         if (colormapped)
6848         {
6849                 skinframe->qgeneratebase = false;
6850                 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);
6851                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6852                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6853         }
6854         else
6855         {
6856                 skinframe->qgeneratemerged = false;
6857                 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);
6858         }
6859
6860         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6861         {
6862                 Mem_Free(skinframe->qpixels);
6863                 skinframe->qpixels = NULL;
6864         }
6865 }
6866
6867 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)
6868 {
6869         int i;
6870         skinframe_t *skinframe;
6871
6872         if (cls.state == ca_dedicated)
6873                 return NULL;
6874
6875         // if already loaded just return it, otherwise make a new skinframe
6876         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6877         if (skinframe && skinframe->base)
6878                 return skinframe;
6879
6880         skinframe->stain = NULL;
6881         skinframe->merged = NULL;
6882         skinframe->base = NULL;
6883         skinframe->pants = NULL;
6884         skinframe->shirt = NULL;
6885         skinframe->nmap = NULL;
6886         skinframe->gloss = NULL;
6887         skinframe->glow = NULL;
6888         skinframe->fog = NULL;
6889         skinframe->reflect = NULL;
6890         skinframe->hasalpha = false;
6891
6892         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6893         if (!skindata)
6894                 return NULL;
6895
6896         if (developer_loading.integer)
6897                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6898
6899         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6900         if (textureflags & TEXF_ALPHA)
6901         {
6902                 for (i = 0;i < width * height;i++)
6903                 {
6904                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6905                         {
6906                                 skinframe->hasalpha = true;
6907                                 break;
6908                         }
6909                 }
6910                 if (r_loadfog && skinframe->hasalpha)
6911                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6912         }
6913
6914         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6915         //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]);
6916
6917         return skinframe;
6918 }
6919
6920 skinframe_t *R_SkinFrame_LoadMissing(void)
6921 {
6922         skinframe_t *skinframe;
6923
6924         if (cls.state == ca_dedicated)
6925                 return NULL;
6926
6927         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6928         skinframe->stain = NULL;
6929         skinframe->merged = NULL;
6930         skinframe->base = NULL;
6931         skinframe->pants = NULL;
6932         skinframe->shirt = NULL;
6933         skinframe->nmap = NULL;
6934         skinframe->gloss = NULL;
6935         skinframe->glow = NULL;
6936         skinframe->fog = NULL;
6937         skinframe->reflect = NULL;
6938         skinframe->hasalpha = false;
6939
6940         skinframe->avgcolor[0] = rand() / RAND_MAX;
6941         skinframe->avgcolor[1] = rand() / RAND_MAX;
6942         skinframe->avgcolor[2] = rand() / RAND_MAX;
6943         skinframe->avgcolor[3] = 1;
6944
6945         return skinframe;
6946 }
6947
6948 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6949 typedef struct suffixinfo_s
6950 {
6951         const char *suffix;
6952         qboolean flipx, flipy, flipdiagonal;
6953 }
6954 suffixinfo_t;
6955 static suffixinfo_t suffix[3][6] =
6956 {
6957         {
6958                 {"px",   false, false, false},
6959                 {"nx",   false, false, false},
6960                 {"py",   false, false, false},
6961                 {"ny",   false, false, false},
6962                 {"pz",   false, false, false},
6963                 {"nz",   false, false, false}
6964         },
6965         {
6966                 {"posx", false, false, false},
6967                 {"negx", false, false, false},
6968                 {"posy", false, false, false},
6969                 {"negy", false, false, false},
6970                 {"posz", false, false, false},
6971                 {"negz", false, false, false}
6972         },
6973         {
6974                 {"rt",    true, false,  true},
6975                 {"lf",   false,  true,  true},
6976                 {"ft",    true,  true, false},
6977                 {"bk",   false, false, false},
6978                 {"up",    true, false,  true},
6979                 {"dn",    true, false,  true}
6980         }
6981 };
6982
6983 static int componentorder[4] = {0, 1, 2, 3};
6984
6985 rtexture_t *R_LoadCubemap(const char *basename)
6986 {
6987         int i, j, cubemapsize;
6988         unsigned char *cubemappixels, *image_buffer;
6989         rtexture_t *cubemaptexture;
6990         char name[256];
6991         // must start 0 so the first loadimagepixels has no requested width/height
6992         cubemapsize = 0;
6993         cubemappixels = NULL;
6994         cubemaptexture = NULL;
6995         // keep trying different suffix groups (posx, px, rt) until one loads
6996         for (j = 0;j < 3 && !cubemappixels;j++)
6997         {
6998                 // load the 6 images in the suffix group
6999                 for (i = 0;i < 6;i++)
7000                 {
7001                         // generate an image name based on the base and and suffix
7002                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7003                         // load it
7004                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7005                         {
7006                                 // an image loaded, make sure width and height are equal
7007                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7008                                 {
7009                                         // if this is the first image to load successfully, allocate the cubemap memory
7010                                         if (!cubemappixels && image_width >= 1)
7011                                         {
7012                                                 cubemapsize = image_width;
7013                                                 // note this clears to black, so unavailable sides are black
7014                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7015                                         }
7016                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7017                                         if (cubemappixels)
7018                                                 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);
7019                                 }
7020                                 else
7021                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7022                                 // free the image
7023                                 Mem_Free(image_buffer);
7024                         }
7025                 }
7026         }
7027         // if a cubemap loaded, upload it
7028         if (cubemappixels)
7029         {
7030                 if (developer_loading.integer)
7031                         Con_Printf("loading cubemap \"%s\"\n", basename);
7032
7033                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7034                 Mem_Free(cubemappixels);
7035         }
7036         else
7037         {
7038                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7039                 if (developer_loading.integer)
7040                 {
7041                         Con_Printf("(tried tried images ");
7042                         for (j = 0;j < 3;j++)
7043                                 for (i = 0;i < 6;i++)
7044                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7045                         Con_Print(" and was unable to find any of them).\n");
7046                 }
7047         }
7048         return cubemaptexture;
7049 }
7050
7051 rtexture_t *R_GetCubemap(const char *basename)
7052 {
7053         int i;
7054         for (i = 0;i < r_texture_numcubemaps;i++)
7055                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7056                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7057         if (i >= MAX_CUBEMAPS)
7058                 return r_texture_whitecube;
7059         r_texture_numcubemaps++;
7060         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7061         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7062         return r_texture_cubemaps[i].texture;
7063 }
7064
7065 void R_FreeCubemaps(void)
7066 {
7067         int i;
7068         for (i = 0;i < r_texture_numcubemaps;i++)
7069         {
7070                 if (developer_loading.integer)
7071                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7072                 if (r_texture_cubemaps[i].texture)
7073                         R_FreeTexture(r_texture_cubemaps[i].texture);
7074         }
7075         r_texture_numcubemaps = 0;
7076 }
7077
7078 void R_Main_FreeViewCache(void)
7079 {
7080         if (r_refdef.viewcache.entityvisible)
7081                 Mem_Free(r_refdef.viewcache.entityvisible);
7082         if (r_refdef.viewcache.world_pvsbits)
7083                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7084         if (r_refdef.viewcache.world_leafvisible)
7085                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7086         if (r_refdef.viewcache.world_surfacevisible)
7087                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7088         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7089 }
7090
7091 void R_Main_ResizeViewCache(void)
7092 {
7093         int numentities = r_refdef.scene.numentities;
7094         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7095         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7096         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7097         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7098         if (r_refdef.viewcache.maxentities < numentities)
7099         {
7100                 r_refdef.viewcache.maxentities = numentities;
7101                 if (r_refdef.viewcache.entityvisible)
7102                         Mem_Free(r_refdef.viewcache.entityvisible);
7103                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7104         }
7105         if (r_refdef.viewcache.world_numclusters != numclusters)
7106         {
7107                 r_refdef.viewcache.world_numclusters = numclusters;
7108                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7109                 if (r_refdef.viewcache.world_pvsbits)
7110                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7111                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7112         }
7113         if (r_refdef.viewcache.world_numleafs != numleafs)
7114         {
7115                 r_refdef.viewcache.world_numleafs = numleafs;
7116                 if (r_refdef.viewcache.world_leafvisible)
7117                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7118                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7119         }
7120         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7121         {
7122                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7123                 if (r_refdef.viewcache.world_surfacevisible)
7124                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7125                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7126         }
7127 }
7128
7129 extern rtexture_t *loadingscreentexture;
7130 void gl_main_start(void)
7131 {
7132         loadingscreentexture = NULL;
7133         r_texture_blanknormalmap = NULL;
7134         r_texture_white = NULL;
7135         r_texture_grey128 = NULL;
7136         r_texture_black = NULL;
7137         r_texture_whitecube = NULL;
7138         r_texture_normalizationcube = NULL;
7139         r_texture_fogattenuation = NULL;
7140         r_texture_fogheighttexture = NULL;
7141         r_texture_gammaramps = NULL;
7142         r_texture_numcubemaps = 0;
7143
7144         r_loaddds = r_texture_dds_load.integer;
7145         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7146
7147         switch(vid.renderpath)
7148         {
7149         case RENDERPATH_GL20:
7150         case RENDERPATH_CGGL:
7151         case RENDERPATH_D3D9:
7152         case RENDERPATH_D3D10:
7153         case RENDERPATH_D3D11:
7154                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7155                 Cvar_SetValueQuick(&gl_combine, 1);
7156                 Cvar_SetValueQuick(&r_glsl, 1);
7157                 r_loadnormalmap = true;
7158                 r_loadgloss = true;
7159                 r_loadfog = false;
7160                 break;
7161         case RENDERPATH_GL13:
7162                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7163                 Cvar_SetValueQuick(&gl_combine, 1);
7164                 Cvar_SetValueQuick(&r_glsl, 0);
7165                 r_loadnormalmap = false;
7166                 r_loadgloss = false;
7167                 r_loadfog = true;
7168                 break;
7169         case RENDERPATH_GL11:
7170                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7171                 Cvar_SetValueQuick(&gl_combine, 0);
7172                 Cvar_SetValueQuick(&r_glsl, 0);
7173                 r_loadnormalmap = false;
7174                 r_loadgloss = false;
7175                 r_loadfog = true;
7176                 break;
7177         }
7178
7179         R_AnimCache_Free();
7180         R_FrameData_Reset();
7181
7182         r_numqueries = 0;
7183         r_maxqueries = 0;
7184         memset(r_queries, 0, sizeof(r_queries));
7185
7186         r_qwskincache = NULL;
7187         r_qwskincache_size = 0;
7188
7189         // set up r_skinframe loading system for textures
7190         memset(&r_skinframe, 0, sizeof(r_skinframe));
7191         r_skinframe.loadsequence = 1;
7192         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7193
7194         r_main_texturepool = R_AllocTexturePool();
7195         R_BuildBlankTextures();
7196         R_BuildNoTexture();
7197         if (vid.support.arb_texture_cube_map)
7198         {
7199                 R_BuildWhiteCube();
7200                 R_BuildNormalizationCube();
7201         }
7202         r_texture_fogattenuation = NULL;
7203         r_texture_fogheighttexture = NULL;
7204         r_texture_gammaramps = NULL;
7205         //r_texture_fogintensity = NULL;
7206         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7207         memset(&r_waterstate, 0, sizeof(r_waterstate));
7208         r_glsl_permutation = NULL;
7209         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7210         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7211         glslshaderstring = NULL;
7212 #ifdef SUPPORTCG
7213         r_cg_permutation = NULL;
7214         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7215         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7216         cgshaderstring = NULL;
7217 #endif
7218 #ifdef SUPPORTD3D
7219         r_hlsl_permutation = NULL;
7220         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7221         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7222         hlslshaderstring = NULL;
7223 #endif
7224         memset(&r_svbsp, 0, sizeof (r_svbsp));
7225
7226         r_refdef.fogmasktable_density = 0;
7227 }
7228
7229 void gl_main_shutdown(void)
7230 {
7231         R_AnimCache_Free();
7232         R_FrameData_Reset();
7233
7234         R_Main_FreeViewCache();
7235
7236         switch(vid.renderpath)
7237         {
7238         case RENDERPATH_GL11:
7239         case RENDERPATH_GL13:
7240         case RENDERPATH_GL20:
7241         case RENDERPATH_CGGL:
7242                 if (r_maxqueries)
7243                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7244                 break;
7245         case RENDERPATH_D3D9:
7246                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7247                 break;
7248         case RENDERPATH_D3D10:
7249                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7250                 break;
7251         case RENDERPATH_D3D11:
7252                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7253                 break;
7254         }
7255
7256         r_numqueries = 0;
7257         r_maxqueries = 0;
7258         memset(r_queries, 0, sizeof(r_queries));
7259
7260         r_qwskincache = NULL;
7261         r_qwskincache_size = 0;
7262
7263         // clear out the r_skinframe state
7264         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7265         memset(&r_skinframe, 0, sizeof(r_skinframe));
7266
7267         if (r_svbsp.nodes)
7268                 Mem_Free(r_svbsp.nodes);
7269         memset(&r_svbsp, 0, sizeof (r_svbsp));
7270         R_FreeTexturePool(&r_main_texturepool);
7271         loadingscreentexture = NULL;
7272         r_texture_blanknormalmap = NULL;
7273         r_texture_white = NULL;
7274         r_texture_grey128 = NULL;
7275         r_texture_black = NULL;
7276         r_texture_whitecube = NULL;
7277         r_texture_normalizationcube = NULL;
7278         r_texture_fogattenuation = NULL;
7279         r_texture_fogheighttexture = NULL;
7280         r_texture_gammaramps = NULL;
7281         r_texture_numcubemaps = 0;
7282         //r_texture_fogintensity = NULL;
7283         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7284         memset(&r_waterstate, 0, sizeof(r_waterstate));
7285         R_GLSL_Restart_f();
7286
7287         r_glsl_permutation = NULL;
7288         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7289         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7290         glslshaderstring = NULL;
7291 #ifdef SUPPORTCG
7292         r_cg_permutation = NULL;
7293         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7294         Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7295         cgshaderstring = NULL;
7296 #endif
7297 #ifdef SUPPORTD3D
7298         r_hlsl_permutation = NULL;
7299         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7300         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7301         hlslshaderstring = NULL;
7302 #endif
7303 }
7304
7305 extern void CL_ParseEntityLump(char *entitystring);
7306 void gl_main_newmap(void)
7307 {
7308         // FIXME: move this code to client
7309         char *entities, entname[MAX_QPATH];
7310         if (r_qwskincache)
7311                 Mem_Free(r_qwskincache);
7312         r_qwskincache = NULL;
7313         r_qwskincache_size = 0;
7314         if (cl.worldmodel)
7315         {
7316                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7317                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7318                 {
7319                         CL_ParseEntityLump(entities);
7320                         Mem_Free(entities);
7321                         return;
7322                 }
7323                 if (cl.worldmodel->brush.entities)
7324                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7325         }
7326         R_Main_FreeViewCache();
7327
7328         R_FrameData_Reset();
7329 }
7330
7331 void GL_Main_Init(void)
7332 {
7333         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7334
7335         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7336         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7337         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7338         if (gamemode == GAME_NEHAHRA)
7339         {
7340                 Cvar_RegisterVariable (&gl_fogenable);
7341                 Cvar_RegisterVariable (&gl_fogdensity);
7342                 Cvar_RegisterVariable (&gl_fogred);
7343                 Cvar_RegisterVariable (&gl_foggreen);
7344                 Cvar_RegisterVariable (&gl_fogblue);
7345                 Cvar_RegisterVariable (&gl_fogstart);
7346                 Cvar_RegisterVariable (&gl_fogend);
7347                 Cvar_RegisterVariable (&gl_skyclip);
7348         }
7349         Cvar_RegisterVariable(&r_motionblur);
7350         Cvar_RegisterVariable(&r_motionblur_maxblur);
7351         Cvar_RegisterVariable(&r_motionblur_bmin);
7352         Cvar_RegisterVariable(&r_motionblur_vmin);
7353         Cvar_RegisterVariable(&r_motionblur_vmax);
7354         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7355         Cvar_RegisterVariable(&r_motionblur_randomize);
7356         Cvar_RegisterVariable(&r_damageblur);
7357         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7358         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7359         Cvar_RegisterVariable(&r_equalize_entities_by);
7360         Cvar_RegisterVariable(&r_equalize_entities_to);
7361         Cvar_RegisterVariable(&r_depthfirst);
7362         Cvar_RegisterVariable(&r_useinfinitefarclip);
7363         Cvar_RegisterVariable(&r_farclip_base);
7364         Cvar_RegisterVariable(&r_farclip_world);
7365         Cvar_RegisterVariable(&r_nearclip);
7366         Cvar_RegisterVariable(&r_showbboxes);
7367         Cvar_RegisterVariable(&r_showsurfaces);
7368         Cvar_RegisterVariable(&r_showtris);
7369         Cvar_RegisterVariable(&r_shownormals);
7370         Cvar_RegisterVariable(&r_showlighting);
7371         Cvar_RegisterVariable(&r_showshadowvolumes);
7372         Cvar_RegisterVariable(&r_showcollisionbrushes);
7373         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7374         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7375         Cvar_RegisterVariable(&r_showdisabledepthtest);
7376         Cvar_RegisterVariable(&r_drawportals);
7377         Cvar_RegisterVariable(&r_drawentities);
7378         Cvar_RegisterVariable(&r_draw2d);
7379         Cvar_RegisterVariable(&r_drawworld);
7380         Cvar_RegisterVariable(&r_cullentities_trace);
7381         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7382         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7383         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7384         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7385         Cvar_RegisterVariable(&r_drawviewmodel);
7386         Cvar_RegisterVariable(&r_drawexteriormodel);
7387         Cvar_RegisterVariable(&r_speeds);
7388         Cvar_RegisterVariable(&r_fullbrights);
7389         Cvar_RegisterVariable(&r_wateralpha);
7390         Cvar_RegisterVariable(&r_dynamic);
7391         Cvar_RegisterVariable(&r_fakelight);
7392         Cvar_RegisterVariable(&r_fakelight_intensity);
7393         Cvar_RegisterVariable(&r_fullbright);
7394         Cvar_RegisterVariable(&r_shadows);
7395         Cvar_RegisterVariable(&r_shadows_darken);
7396         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7397         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7398         Cvar_RegisterVariable(&r_shadows_throwdistance);
7399         Cvar_RegisterVariable(&r_shadows_throwdirection);
7400         Cvar_RegisterVariable(&r_shadows_focus);
7401         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7402         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7403         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7404         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7405         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7406         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7407         Cvar_RegisterVariable(&r_fog_exp2);
7408         Cvar_RegisterVariable(&r_drawfog);
7409         Cvar_RegisterVariable(&r_transparentdepthmasking);
7410         Cvar_RegisterVariable(&r_texture_dds_load);
7411         Cvar_RegisterVariable(&r_texture_dds_save);
7412         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7413         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7414         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7415         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7416         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7417         Cvar_RegisterVariable(&r_textureunits);
7418         Cvar_RegisterVariable(&gl_combine);
7419         Cvar_RegisterVariable(&r_glsl);
7420         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7421         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7422         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7423         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7424         Cvar_RegisterVariable(&r_glsl_postprocess);
7425         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7426         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7427         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7428         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7429         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7430         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7431         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7432         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7433
7434         Cvar_RegisterVariable(&r_water);
7435         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7436         Cvar_RegisterVariable(&r_water_clippingplanebias);
7437         Cvar_RegisterVariable(&r_water_refractdistort);
7438         Cvar_RegisterVariable(&r_water_reflectdistort);
7439         Cvar_RegisterVariable(&r_water_scissormode);
7440         Cvar_RegisterVariable(&r_lerpsprites);
7441         Cvar_RegisterVariable(&r_lerpmodels);
7442         Cvar_RegisterVariable(&r_lerplightstyles);
7443         Cvar_RegisterVariable(&r_waterscroll);
7444         Cvar_RegisterVariable(&r_bloom);
7445         Cvar_RegisterVariable(&r_bloom_colorscale);
7446         Cvar_RegisterVariable(&r_bloom_brighten);
7447         Cvar_RegisterVariable(&r_bloom_blur);
7448         Cvar_RegisterVariable(&r_bloom_resolution);
7449         Cvar_RegisterVariable(&r_bloom_colorexponent);
7450         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7451         Cvar_RegisterVariable(&r_hdr);
7452         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7453         Cvar_RegisterVariable(&r_hdr_glowintensity);
7454         Cvar_RegisterVariable(&r_hdr_range);
7455         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7456         Cvar_RegisterVariable(&developer_texturelogging);
7457         Cvar_RegisterVariable(&gl_lightmaps);
7458         Cvar_RegisterVariable(&r_test);
7459         Cvar_RegisterVariable(&r_glsl_saturation);
7460         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7461         Cvar_RegisterVariable(&r_framedatasize);
7462         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7463                 Cvar_SetValue("r_fullbrights", 0);
7464         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7465
7466         Cvar_RegisterVariable(&r_track_sprites);
7467         Cvar_RegisterVariable(&r_track_sprites_flags);
7468         Cvar_RegisterVariable(&r_track_sprites_scalew);
7469         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7470         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7471         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7472         Cvar_RegisterVariable(&r_overheadsprites_scalex);
7473         Cvar_RegisterVariable(&r_overheadsprites_scaley);
7474 }
7475
7476 extern void R_Textures_Init(void);
7477 extern void GL_Draw_Init(void);
7478 extern void GL_Main_Init(void);
7479 extern void R_Shadow_Init(void);
7480 extern void R_Sky_Init(void);
7481 extern void GL_Surf_Init(void);
7482 extern void R_Particles_Init(void);
7483 extern void R_Explosion_Init(void);
7484 extern void gl_backend_init(void);
7485 extern void Sbar_Init(void);
7486 extern void R_LightningBeams_Init(void);
7487 extern void Mod_RenderInit(void);
7488 extern void Font_Init(void);
7489
7490 void Render_Init(void)
7491 {
7492         gl_backend_init();
7493         R_Textures_Init();
7494         GL_Main_Init();
7495         Font_Init();
7496         GL_Draw_Init();
7497         R_Shadow_Init();
7498         R_Sky_Init();
7499         GL_Surf_Init();
7500         Sbar_Init();
7501         R_Particles_Init();
7502         R_Explosion_Init();
7503         R_LightningBeams_Init();
7504         Mod_RenderInit();
7505 }
7506
7507 /*
7508 ===============
7509 GL_Init
7510 ===============
7511 */
7512 extern char *ENGINE_EXTENSIONS;
7513 void GL_Init (void)
7514 {
7515         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7516         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7517         gl_version = (const char *)qglGetString(GL_VERSION);
7518         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7519
7520         if (!gl_extensions)
7521                 gl_extensions = "";
7522         if (!gl_platformextensions)
7523                 gl_platformextensions = "";
7524
7525         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7526         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7527         Con_Printf("GL_VERSION: %s\n", gl_version);
7528         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7529         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7530
7531         VID_CheckExtensions();
7532
7533         // LordHavoc: report supported extensions
7534         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7535
7536         // clear to black (loading plaque will be seen over this)
7537         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7538 }
7539
7540 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7541 {
7542         int i;
7543         mplane_t *p;
7544         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7545         {
7546                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7547                 if (i == 4)
7548                         continue;
7549                 p = r_refdef.view.frustum + i;
7550                 switch(p->signbits)
7551                 {
7552                 default:
7553                 case 0:
7554                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7555                                 return true;
7556                         break;
7557                 case 1:
7558                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7559                                 return true;
7560                         break;
7561                 case 2:
7562                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7563                                 return true;
7564                         break;
7565                 case 3:
7566                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7567                                 return true;
7568                         break;
7569                 case 4:
7570                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7571                                 return true;
7572                         break;
7573                 case 5:
7574                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7575                                 return true;
7576                         break;
7577                 case 6:
7578                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7579                                 return true;
7580                         break;
7581                 case 7:
7582                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7583                                 return true;
7584                         break;
7585                 }
7586         }
7587         return false;
7588 }
7589
7590 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7591 {
7592         int i;
7593         const mplane_t *p;
7594         for (i = 0;i < numplanes;i++)
7595         {
7596                 p = planes + i;
7597                 switch(p->signbits)
7598                 {
7599                 default:
7600                 case 0:
7601                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7602                                 return true;
7603                         break;
7604                 case 1:
7605                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7606                                 return true;
7607                         break;
7608                 case 2:
7609                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7610                                 return true;
7611                         break;
7612                 case 3:
7613                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7614                                 return true;
7615                         break;
7616                 case 4:
7617                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7618                                 return true;
7619                         break;
7620                 case 5:
7621                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7622                                 return true;
7623                         break;
7624                 case 6:
7625                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7626                                 return true;
7627                         break;
7628                 case 7:
7629                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7630                                 return true;
7631                         break;
7632                 }
7633         }
7634         return false;
7635 }
7636
7637 //==================================================================================
7638
7639 // LordHavoc: this stores temporary data used within the same frame
7640
7641 qboolean r_framedata_failed;
7642 static size_t r_framedata_size;
7643 static size_t r_framedata_current;
7644 static void *r_framedata_base;
7645
7646 void R_FrameData_Reset(void)
7647 {
7648         if (r_framedata_base)
7649                 Mem_Free(r_framedata_base);
7650         r_framedata_base = NULL;
7651         r_framedata_size = 0;
7652         r_framedata_current = 0;
7653         r_framedata_failed = false;
7654 }
7655
7656 void R_FrameData_NewFrame(void)
7657 {
7658         size_t wantedsize;
7659         if (r_framedata_failed)
7660                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7661         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7662         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7663         if (r_framedata_size != wantedsize)
7664         {
7665                 r_framedata_size = wantedsize;
7666                 if (r_framedata_base)
7667                         Mem_Free(r_framedata_base);
7668                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7669         }
7670         r_framedata_current = 0;
7671         r_framedata_failed = false;
7672 }
7673
7674 void *R_FrameData_Alloc(size_t size)
7675 {
7676         void *data;
7677
7678         // align to 16 byte boundary
7679         size = (size + 15) & ~15;
7680         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7681         r_framedata_current += size;
7682
7683         // check overflow
7684         if (r_framedata_current > r_framedata_size)
7685                 r_framedata_failed = true;
7686
7687         // return NULL on everything after a failure
7688         if (r_framedata_failed)
7689                 return NULL;
7690
7691         return data;
7692 }
7693
7694 void *R_FrameData_Store(size_t size, void *data)
7695 {
7696         void *d = R_FrameData_Alloc(size);
7697         if (d)
7698                 memcpy(d, data, size);
7699         return d;
7700 }
7701
7702 //==================================================================================
7703
7704 // LordHavoc: animcache originally written by Echon, rewritten since then
7705
7706 /**
7707  * Animation cache prevents re-generating mesh data for an animated model
7708  * multiple times in one frame for lighting, shadowing, reflections, etc.
7709  */
7710
7711 void R_AnimCache_Free(void)
7712 {
7713 }
7714
7715 void R_AnimCache_ClearCache(void)
7716 {
7717         int i;
7718         entity_render_t *ent;
7719
7720         for (i = 0;i < r_refdef.scene.numentities;i++)
7721         {
7722                 ent = r_refdef.scene.entities[i];
7723                 ent->animcache_vertex3f = NULL;
7724                 ent->animcache_normal3f = NULL;
7725                 ent->animcache_svector3f = NULL;
7726                 ent->animcache_tvector3f = NULL;
7727                 ent->animcache_vertexposition = NULL;
7728                 ent->animcache_vertexmesh = NULL;
7729                 ent->animcache_vertexpositionbuffer = NULL;
7730                 ent->animcache_vertexmeshbuffer = NULL;
7731         }
7732 }
7733
7734 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7735 {
7736         int i;
7737
7738         // identical memory layout, so no need to allocate...
7739         // this also provides the vertexposition structure to everything, e.g.
7740         // depth masked rendering currently uses it even if having separate
7741         // arrays
7742         // NOTE: get rid of this optimization if changing it to e.g. 4f
7743         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7744
7745         // TODO:
7746         // get rid of following uses of VERTEXPOSITION, change to the array:
7747         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7748         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7749         // R_DrawTextureSurfaceList_DepthOnly
7750         // R_Q1BSP_DrawShadowMap
7751
7752         switch(vid.renderpath)
7753         {
7754         case RENDERPATH_GL20:
7755         case RENDERPATH_CGGL:
7756                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7757                 if (gl_mesh_separatearrays.integer)
7758                         return;
7759                 break;
7760         case RENDERPATH_D3D9:
7761         case RENDERPATH_D3D10:
7762         case RENDERPATH_D3D11:
7763                 // always need the meshbuffers
7764                 break;
7765         case RENDERPATH_GL13:
7766         case RENDERPATH_GL11:
7767                 // never need the meshbuffers
7768                 return;
7769         }
7770
7771         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7772                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7773         /*
7774         if (!ent->animcache_vertexposition)
7775                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7776         */
7777         if (ent->animcache_vertexposition)
7778         {
7779                 /*
7780                 for (i = 0;i < numvertices;i++)
7781                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7782                 */
7783                 // TODO: upload vertex buffer?
7784         }
7785         if (ent->animcache_vertexmesh)
7786         {
7787                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7788                 for (i = 0;i < numvertices;i++)
7789                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7790                 if (ent->animcache_svector3f)
7791                         for (i = 0;i < numvertices;i++)
7792                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7793                 if (ent->animcache_tvector3f)
7794                         for (i = 0;i < numvertices;i++)
7795                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7796                 if (ent->animcache_normal3f)
7797                         for (i = 0;i < numvertices;i++)
7798                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7799                 // TODO: upload vertex buffer?
7800         }
7801 }
7802
7803 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7804 {
7805         dp_model_t *model = ent->model;
7806         int numvertices;
7807         // see if it's already cached this frame
7808         if (ent->animcache_vertex3f)
7809         {
7810                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7811                 if (wantnormals || wanttangents)
7812                 {
7813                         if (ent->animcache_normal3f)
7814                                 wantnormals = false;
7815                         if (ent->animcache_svector3f)
7816                                 wanttangents = false;
7817                         if (wantnormals || wanttangents)
7818                         {
7819                                 numvertices = model->surfmesh.num_vertices;
7820                                 if (wantnormals)
7821                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7822                                 if (wanttangents)
7823                                 {
7824                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7825                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7826                                 }
7827                                 if (!r_framedata_failed)
7828                                 {
7829                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7830                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7831                                 }
7832                         }
7833                 }
7834         }
7835         else
7836         {
7837                 // see if this ent is worth caching
7838                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7839                         return false;
7840                 // get some memory for this entity and generate mesh data
7841                 numvertices = model->surfmesh.num_vertices;
7842                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7843                 if (wantnormals)
7844                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7845                 if (wanttangents)
7846                 {
7847                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7848                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7849                 }
7850                 if (!r_framedata_failed)
7851                 {
7852                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7853                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7854                 }
7855         }
7856         return !r_framedata_failed;
7857 }
7858
7859 void R_AnimCache_CacheVisibleEntities(void)
7860 {
7861         int i;
7862         qboolean wantnormals = true;
7863         qboolean wanttangents = !r_showsurfaces.integer;
7864
7865         switch(vid.renderpath)
7866         {
7867         case RENDERPATH_GL20:
7868         case RENDERPATH_CGGL:
7869         case RENDERPATH_D3D9:
7870         case RENDERPATH_D3D10:
7871         case RENDERPATH_D3D11:
7872                 break;
7873         case RENDERPATH_GL13:
7874         case RENDERPATH_GL11:
7875                 wanttangents = false;
7876                 break;
7877         }
7878
7879         if (r_shownormals.integer)
7880                 wanttangents = wantnormals = true;
7881
7882         // TODO: thread this
7883         // NOTE: R_PrepareRTLights() also caches entities
7884
7885         for (i = 0;i < r_refdef.scene.numentities;i++)
7886                 if (r_refdef.viewcache.entityvisible[i])
7887                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7888 }
7889
7890 //==================================================================================
7891
7892 static void R_View_UpdateEntityLighting (void)
7893 {
7894         int i;
7895         entity_render_t *ent;
7896         vec3_t tempdiffusenormal, avg;
7897         vec_t f, fa, fd, fdd;
7898         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7899
7900         for (i = 0;i < r_refdef.scene.numentities;i++)
7901         {
7902                 ent = r_refdef.scene.entities[i];
7903
7904                 // skip unseen models
7905                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7906                         continue;
7907
7908                 // skip bsp models
7909                 if (ent->model && ent->model->brush.num_leafs)
7910                 {
7911                         // TODO: use modellight for r_ambient settings on world?
7912                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7913                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7914                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7915                         continue;
7916                 }
7917
7918                 // fetch the lighting from the worldmodel data
7919                 VectorClear(ent->modellight_ambient);
7920                 VectorClear(ent->modellight_diffuse);
7921                 VectorClear(tempdiffusenormal);
7922                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7923                 {
7924                         vec3_t org;
7925                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7926
7927                         // complete lightning for lit sprites
7928                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7929                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7930                         {
7931                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7932                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7933                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7934                         }
7935                         else
7936                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7937
7938                         if(ent->flags & RENDER_EQUALIZE)
7939                         {
7940                                 // first fix up ambient lighting...
7941                                 if(r_equalize_entities_minambient.value > 0)
7942                                 {
7943                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7944                                         if(fd > 0)
7945                                         {
7946                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7947                                                 if(fa < r_equalize_entities_minambient.value * fd)
7948                                                 {
7949                                                         // solve:
7950                                                         //   fa'/fd' = minambient
7951                                                         //   fa'+0.25*fd' = fa+0.25*fd
7952                                                         //   ...
7953                                                         //   fa' = fd' * minambient
7954                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7955                                                         //   ...
7956                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7957                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7958                                                         //   ...
7959                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7960                                                         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
7961                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7962                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7963                                                 }
7964                                         }
7965                                 }
7966
7967                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7968                                 {
7969                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7970                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7971                                         f = fa + 0.25 * fd;
7972                                         if(f > 0)
7973                                         {
7974                                                 // adjust brightness and saturation to target
7975                                                 avg[0] = avg[1] = avg[2] = fa / f;
7976                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7977                                                 avg[0] = avg[1] = avg[2] = fd / f;
7978                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7979                                         }
7980                                 }
7981                         }
7982                 }
7983                 else // highly rare
7984                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7985
7986                 // move the light direction into modelspace coordinates for lighting code
7987                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7988                 if(VectorLength2(ent->modellight_lightdir) == 0)
7989                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7990                 VectorNormalize(ent->modellight_lightdir);
7991         }
7992 }
7993
7994 #define MAX_LINEOFSIGHTTRACES 64
7995
7996 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7997 {
7998         int i;
7999         vec3_t boxmins, boxmaxs;
8000         vec3_t start;
8001         vec3_t end;
8002         dp_model_t *model = r_refdef.scene.worldmodel;
8003
8004         if (!model || !model->brush.TraceLineOfSight)
8005                 return true;
8006
8007         // expand the box a little
8008         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8009         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8010         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8011         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8012         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8013         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8014
8015         // return true if eye is inside enlarged box
8016         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8017                 return true;
8018
8019         // try center
8020         VectorCopy(eye, start);
8021         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8022         if (model->brush.TraceLineOfSight(model, start, end))
8023                 return true;
8024
8025         // try various random positions
8026         for (i = 0;i < numsamples;i++)
8027         {
8028                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8029                 if (model->brush.TraceLineOfSight(model, start, end))
8030                         return true;
8031         }
8032
8033         return false;
8034 }
8035
8036
8037 static void R_View_UpdateEntityVisible (void)
8038 {
8039         int i;
8040         int renderimask;
8041         int samples;
8042         entity_render_t *ent;
8043
8044         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8045                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8046                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8047                 :                                                          RENDER_EXTERIORMODEL;
8048         if (!r_drawviewmodel.integer)
8049                 renderimask |= RENDER_VIEWMODEL;
8050         if (!r_drawexteriormodel.integer)
8051                 renderimask |= RENDER_EXTERIORMODEL;
8052         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8053         {
8054                 // worldmodel can check visibility
8055                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8056                 for (i = 0;i < r_refdef.scene.numentities;i++)
8057                 {
8058                         ent = r_refdef.scene.entities[i];
8059                         if (!(ent->flags & renderimask))
8060                         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)))
8061                         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))
8062                                 r_refdef.viewcache.entityvisible[i] = true;
8063                 }
8064                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8065                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8066                 {
8067                         for (i = 0;i < r_refdef.scene.numentities;i++)
8068                         {
8069                                 ent = r_refdef.scene.entities[i];
8070                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8071                                 {
8072                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8073                                         if (samples < 0)
8074                                                 continue; // temp entities do pvs only
8075                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8076                                                 ent->last_trace_visibility = realtime;
8077                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8078                                                 r_refdef.viewcache.entityvisible[i] = 0;
8079                                 }
8080                         }
8081                 }
8082         }
8083         else
8084         {
8085                 // no worldmodel or it can't check visibility
8086                 for (i = 0;i < r_refdef.scene.numentities;i++)
8087                 {
8088                         ent = r_refdef.scene.entities[i];
8089                         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));
8090                 }
8091         }
8092 }
8093
8094 /// only used if skyrendermasked, and normally returns false
8095 int R_DrawBrushModelsSky (void)
8096 {
8097         int i, sky;
8098         entity_render_t *ent;
8099
8100         sky = false;
8101         for (i = 0;i < r_refdef.scene.numentities;i++)
8102         {
8103                 if (!r_refdef.viewcache.entityvisible[i])
8104                         continue;
8105                 ent = r_refdef.scene.entities[i];
8106                 if (!ent->model || !ent->model->DrawSky)
8107                         continue;
8108                 ent->model->DrawSky(ent);
8109                 sky = true;
8110         }
8111         return sky;
8112 }
8113
8114 static void R_DrawNoModel(entity_render_t *ent);
8115 static void R_DrawModels(void)
8116 {
8117         int i;
8118         entity_render_t *ent;
8119
8120         for (i = 0;i < r_refdef.scene.numentities;i++)
8121         {
8122                 if (!r_refdef.viewcache.entityvisible[i])
8123                         continue;
8124                 ent = r_refdef.scene.entities[i];
8125                 r_refdef.stats.entities++;
8126                 if (ent->model && ent->model->Draw != NULL)
8127                         ent->model->Draw(ent);
8128                 else
8129                         R_DrawNoModel(ent);
8130         }
8131 }
8132
8133 static void R_DrawModelsDepth(void)
8134 {
8135         int i;
8136         entity_render_t *ent;
8137
8138         for (i = 0;i < r_refdef.scene.numentities;i++)
8139         {
8140                 if (!r_refdef.viewcache.entityvisible[i])
8141                         continue;
8142                 ent = r_refdef.scene.entities[i];
8143                 if (ent->model && ent->model->DrawDepth != NULL)
8144                         ent->model->DrawDepth(ent);
8145         }
8146 }
8147
8148 static void R_DrawModelsDebug(void)
8149 {
8150         int i;
8151         entity_render_t *ent;
8152
8153         for (i = 0;i < r_refdef.scene.numentities;i++)
8154         {
8155                 if (!r_refdef.viewcache.entityvisible[i])
8156                         continue;
8157                 ent = r_refdef.scene.entities[i];
8158                 if (ent->model && ent->model->DrawDebug != NULL)
8159                         ent->model->DrawDebug(ent);
8160         }
8161 }
8162
8163 static void R_DrawModelsAddWaterPlanes(void)
8164 {
8165         int i;
8166         entity_render_t *ent;
8167
8168         for (i = 0;i < r_refdef.scene.numentities;i++)
8169         {
8170                 if (!r_refdef.viewcache.entityvisible[i])
8171                         continue;
8172                 ent = r_refdef.scene.entities[i];
8173                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8174                         ent->model->DrawAddWaterPlanes(ent);
8175         }
8176 }
8177
8178 static void R_View_SetFrustum(const int *scissor)
8179 {
8180         int i;
8181         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8182         vec3_t forward, left, up, origin, v;
8183
8184         if(scissor)
8185         {
8186                 // flipped x coordinates (because x points left here)
8187                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8188                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8189
8190                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8191                 switch(vid.renderpath)
8192                 {
8193                         case RENDERPATH_D3D9:
8194                         case RENDERPATH_D3D10:
8195                         case RENDERPATH_D3D11:
8196                                 // non-flipped y coordinates
8197                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8198                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8199                                 break;
8200                         case RENDERPATH_GL11:
8201                         case RENDERPATH_GL13:
8202                         case RENDERPATH_GL20:
8203                         case RENDERPATH_CGGL:
8204                                 // non-flipped y coordinates
8205                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8206                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8207                                 break;
8208                 }
8209         }
8210
8211         // we can't trust r_refdef.view.forward and friends in reflected scenes
8212         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8213
8214 #if 0
8215         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8216         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8217         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8218         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8219         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8220         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8221         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8222         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8223         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8224         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8225         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8226         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8227 #endif
8228
8229 #if 0
8230         zNear = r_refdef.nearclip;
8231         nudge = 1.0 - 1.0 / (1<<23);
8232         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8233         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8234         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8235         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8236         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8237         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8238         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8239         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8240 #endif
8241
8242
8243
8244 #if 0
8245         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8246         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8247         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8248         r_refdef.view.frustum[0].dist = m[15] - m[12];
8249
8250         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8251         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8252         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8253         r_refdef.view.frustum[1].dist = m[15] + m[12];
8254
8255         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8256         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8257         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8258         r_refdef.view.frustum[2].dist = m[15] - m[13];
8259
8260         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8261         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8262         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8263         r_refdef.view.frustum[3].dist = m[15] + m[13];
8264
8265         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8266         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8267         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8268         r_refdef.view.frustum[4].dist = m[15] - m[14];
8269
8270         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8271         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8272         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8273         r_refdef.view.frustum[5].dist = m[15] + m[14];
8274 #endif
8275
8276         if (r_refdef.view.useperspective)
8277         {
8278                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8279                 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]);
8280                 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]);
8281                 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]);
8282                 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]);
8283
8284                 // then the normals from the corners relative to origin
8285                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8286                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8287                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8288                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8289
8290                 // in a NORMAL view, forward cross left == up
8291                 // in a REFLECTED view, forward cross left == down
8292                 // so our cross products above need to be adjusted for a left handed coordinate system
8293                 CrossProduct(forward, left, v);
8294                 if(DotProduct(v, up) < 0)
8295                 {
8296                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8297                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8298                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8299                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8300                 }
8301
8302                 // Leaving those out was a mistake, those were in the old code, and they
8303                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8304                 // I couldn't reproduce it after adding those normalizations. --blub
8305                 VectorNormalize(r_refdef.view.frustum[0].normal);
8306                 VectorNormalize(r_refdef.view.frustum[1].normal);
8307                 VectorNormalize(r_refdef.view.frustum[2].normal);
8308                 VectorNormalize(r_refdef.view.frustum[3].normal);
8309
8310                 // make the corners absolute
8311                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8312                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8313                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8314                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8315
8316                 // one more normal
8317                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8318
8319                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8320                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8321                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8322                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8323                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8324         }
8325         else
8326         {
8327                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8328                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8329                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8330                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8331                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8332                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8333                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8334                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8335                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8336                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8337         }
8338         r_refdef.view.numfrustumplanes = 5;
8339
8340         if (r_refdef.view.useclipplane)
8341         {
8342                 r_refdef.view.numfrustumplanes = 6;
8343                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8344         }
8345
8346         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8347                 PlaneClassify(r_refdef.view.frustum + i);
8348
8349         // LordHavoc: note to all quake engine coders, Quake had a special case
8350         // for 90 degrees which assumed a square view (wrong), so I removed it,
8351         // Quake2 has it disabled as well.
8352
8353         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8354         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8355         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8356         //PlaneClassify(&frustum[0]);
8357
8358         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8359         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8360         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8361         //PlaneClassify(&frustum[1]);
8362
8363         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8364         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8365         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8366         //PlaneClassify(&frustum[2]);
8367
8368         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8369         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8370         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8371         //PlaneClassify(&frustum[3]);
8372
8373         // nearclip plane
8374         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8375         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8376         //PlaneClassify(&frustum[4]);
8377 }
8378
8379 void R_View_UpdateWithScissor(const int *myscissor)
8380 {
8381         R_Main_ResizeViewCache();
8382         R_View_SetFrustum(myscissor);
8383         R_View_WorldVisibility(r_refdef.view.useclipplane);
8384         R_View_UpdateEntityVisible();
8385         R_View_UpdateEntityLighting();
8386 }
8387
8388 void R_View_Update(void)
8389 {
8390         R_Main_ResizeViewCache();
8391         R_View_SetFrustum(NULL);
8392         R_View_WorldVisibility(r_refdef.view.useclipplane);
8393         R_View_UpdateEntityVisible();
8394         R_View_UpdateEntityLighting();
8395 }
8396
8397 void R_SetupView(qboolean allowwaterclippingplane)
8398 {
8399         const float *customclipplane = NULL;
8400         float plane[4];
8401         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8402         {
8403                 // LordHavoc: couldn't figure out how to make this approach the
8404                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8405                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8406                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8407                         dist = r_refdef.view.clipplane.dist;
8408                 plane[0] = r_refdef.view.clipplane.normal[0];
8409                 plane[1] = r_refdef.view.clipplane.normal[1];
8410                 plane[2] = r_refdef.view.clipplane.normal[2];
8411                 plane[3] = dist;
8412                 customclipplane = plane;
8413         }
8414
8415         if (!r_refdef.view.useperspective)
8416                 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);
8417         else if (vid.stencil && r_useinfinitefarclip.integer)
8418                 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);
8419         else
8420                 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);
8421         R_SetViewport(&r_refdef.view.viewport);
8422 }
8423
8424 void R_EntityMatrix(const matrix4x4_t *matrix)
8425 {
8426         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8427         {
8428                 gl_modelmatrixchanged = false;
8429                 gl_modelmatrix = *matrix;
8430                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8431                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8432                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8433                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8434                 CHECKGLERROR
8435                 switch(vid.renderpath)
8436                 {
8437                 case RENDERPATH_D3D9:
8438 #ifdef SUPPORTD3D
8439                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8440                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8441 #endif
8442                         break;
8443                 case RENDERPATH_D3D10:
8444                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8445                         break;
8446                 case RENDERPATH_D3D11:
8447                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8448                         break;
8449                 case RENDERPATH_GL20:
8450                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8451                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8452                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8453                         break;
8454                 case RENDERPATH_CGGL:
8455 #ifdef SUPPORTCG
8456                         CHECKCGERROR
8457                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8458                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8459                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8460 #endif
8461                         break;
8462                 case RENDERPATH_GL13:
8463                 case RENDERPATH_GL11:
8464                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8465                         break;
8466                 }
8467         }
8468 }
8469
8470 void R_ResetViewRendering2D(void)
8471 {
8472         r_viewport_t viewport;
8473         DrawQ_Finish();
8474
8475         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8476         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);
8477         R_SetViewport(&viewport);
8478         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8479         GL_Color(1, 1, 1, 1);
8480         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8481         GL_BlendFunc(GL_ONE, GL_ZERO);
8482         GL_AlphaTest(false);
8483         GL_ScissorTest(false);
8484         GL_DepthMask(false);
8485         GL_DepthRange(0, 1);
8486         GL_DepthTest(false);
8487         GL_DepthFunc(GL_LEQUAL);
8488         R_EntityMatrix(&identitymatrix);
8489         R_Mesh_ResetTextureState();
8490         GL_PolygonOffset(0, 0);
8491         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8492         switch(vid.renderpath)
8493         {
8494         case RENDERPATH_GL11:
8495         case RENDERPATH_GL13:
8496         case RENDERPATH_GL20:
8497         case RENDERPATH_CGGL:
8498                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8499                 break;
8500         case RENDERPATH_D3D9:
8501         case RENDERPATH_D3D10:
8502         case RENDERPATH_D3D11:
8503                 break;
8504         }
8505         GL_CullFace(GL_NONE);
8506 }
8507
8508 void R_ResetViewRendering3D(void)
8509 {
8510         DrawQ_Finish();
8511
8512         R_SetupView(true);
8513         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8514         GL_Color(1, 1, 1, 1);
8515         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8516         GL_BlendFunc(GL_ONE, GL_ZERO);
8517         GL_AlphaTest(false);
8518         GL_ScissorTest(true);
8519         GL_DepthMask(true);
8520         GL_DepthRange(0, 1);
8521         GL_DepthTest(true);
8522         GL_DepthFunc(GL_LEQUAL);
8523         R_EntityMatrix(&identitymatrix);
8524         R_Mesh_ResetTextureState();
8525         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8526         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8527         switch(vid.renderpath)
8528         {
8529         case RENDERPATH_GL11:
8530         case RENDERPATH_GL13:
8531         case RENDERPATH_GL20:
8532         case RENDERPATH_CGGL:
8533                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8534                 break;
8535         case RENDERPATH_D3D9:
8536         case RENDERPATH_D3D10:
8537         case RENDERPATH_D3D11:
8538                 break;
8539         }
8540         GL_CullFace(r_refdef.view.cullface_back);
8541 }
8542
8543 /*
8544 ================
8545 R_RenderView_UpdateViewVectors
8546 ================
8547 */
8548 static void R_RenderView_UpdateViewVectors(void)
8549 {
8550         // break apart the view matrix into vectors for various purposes
8551         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8552         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8553         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8554         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8555         // make an inverted copy of the view matrix for tracking sprites
8556         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8557 }
8558
8559 void R_RenderScene(void);
8560 void R_RenderWaterPlanes(void);
8561
8562 static void R_Water_StartFrame(void)
8563 {
8564         int i;
8565         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8566         r_waterstate_waterplane_t *p;
8567
8568         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8569                 return;
8570
8571         switch(vid.renderpath)
8572         {
8573         case RENDERPATH_GL20:
8574         case RENDERPATH_CGGL:
8575         case RENDERPATH_D3D9:
8576         case RENDERPATH_D3D10:
8577         case RENDERPATH_D3D11:
8578                 break;
8579         case RENDERPATH_GL13:
8580         case RENDERPATH_GL11:
8581                 return;
8582         }
8583
8584         // set waterwidth and waterheight to the water resolution that will be
8585         // used (often less than the screen resolution for faster rendering)
8586         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8587         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8588
8589         // calculate desired texture sizes
8590         // can't use water if the card does not support the texture size
8591         if (!r_water.integer || r_showsurfaces.integer)
8592                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8593         else if (vid.support.arb_texture_non_power_of_two)
8594         {
8595                 texturewidth = waterwidth;
8596                 textureheight = waterheight;
8597                 camerawidth = waterwidth;
8598                 cameraheight = waterheight;
8599         }
8600         else
8601         {
8602                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8603                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8604                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8605                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8606         }
8607
8608         // allocate textures as needed
8609         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8610         {
8611                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8612                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8613                 {
8614                         if (p->texture_refraction)
8615                                 R_FreeTexture(p->texture_refraction);
8616                         p->texture_refraction = NULL;
8617                         if (p->texture_reflection)
8618                                 R_FreeTexture(p->texture_reflection);
8619                         p->texture_reflection = NULL;
8620                         if (p->texture_camera)
8621                                 R_FreeTexture(p->texture_camera);
8622                         p->texture_camera = NULL;
8623                 }
8624                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8625                 r_waterstate.texturewidth = texturewidth;
8626                 r_waterstate.textureheight = textureheight;
8627                 r_waterstate.camerawidth = camerawidth;
8628                 r_waterstate.cameraheight = cameraheight;
8629         }
8630
8631         if (r_waterstate.texturewidth)
8632         {
8633                 r_waterstate.enabled = true;
8634
8635                 // when doing a reduced render (HDR) we want to use a smaller area
8636                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8637                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8638
8639                 // set up variables that will be used in shader setup
8640                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8641                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8642                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8643                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8644         }
8645
8646         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8647         r_waterstate.numwaterplanes = 0;
8648 }
8649
8650 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8651 {
8652         int triangleindex, planeindex;
8653         const int *e;
8654         vec3_t vert[3];
8655         vec3_t normal;
8656         vec3_t center;
8657         mplane_t plane;
8658         r_waterstate_waterplane_t *p;
8659         texture_t *t = R_GetCurrentTexture(surface->texture);
8660
8661         // just use the first triangle with a valid normal for any decisions
8662         VectorClear(normal);
8663         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8664         {
8665                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8666                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8667                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8668                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8669                 if (VectorLength2(normal) >= 0.001)
8670                         break;
8671         }
8672
8673         VectorCopy(normal, plane.normal);
8674         VectorNormalize(plane.normal);
8675         plane.dist = DotProduct(vert[0], plane.normal);
8676         PlaneClassify(&plane);
8677         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8678         {
8679                 // skip backfaces (except if nocullface is set)
8680                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8681                         return;
8682                 VectorNegate(plane.normal, plane.normal);
8683                 plane.dist *= -1;
8684                 PlaneClassify(&plane);
8685         }
8686
8687
8688         // find a matching plane if there is one
8689         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8690                 if(p->camera_entity == t->camera_entity)
8691                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8692                                 break;
8693         if (planeindex >= r_waterstate.maxwaterplanes)
8694                 return; // nothing we can do, out of planes
8695
8696         // if this triangle does not fit any known plane rendered this frame, add one
8697         if (planeindex >= r_waterstate.numwaterplanes)
8698         {
8699                 // store the new plane
8700                 r_waterstate.numwaterplanes++;
8701                 p->plane = plane;
8702                 // clear materialflags and pvs
8703                 p->materialflags = 0;
8704                 p->pvsvalid = false;
8705                 p->camera_entity = t->camera_entity;
8706                 VectorCopy(surface->mins, p->mins);
8707                 VectorCopy(surface->maxs, p->maxs);
8708         }
8709         else
8710         {
8711                 // merge mins/maxs
8712                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8713                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8714                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8715                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8716                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8717                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8718         }
8719         // merge this surface's materialflags into the waterplane
8720         p->materialflags |= t->currentmaterialflags;
8721         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8722         {
8723                 // merge this surface's PVS into the waterplane
8724                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8725                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8726                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8727                 {
8728                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8729                         p->pvsvalid = true;
8730                 }
8731         }
8732 }
8733
8734 static void R_Water_ProcessPlanes(void)
8735 {
8736         int myscissor[4];
8737         r_refdef_view_t originalview;
8738         r_refdef_view_t myview;
8739         int planeindex;
8740         r_waterstate_waterplane_t *p;
8741         vec3_t visorigin;
8742
8743         originalview = r_refdef.view;
8744
8745         // make sure enough textures are allocated
8746         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8747         {
8748                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8749                 {
8750                         if (!p->texture_refraction)
8751                                 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);
8752                         if (!p->texture_refraction)
8753                                 goto error;
8754                 }
8755                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8756                 {
8757                         if (!p->texture_camera)
8758                                 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);
8759                         if (!p->texture_camera)
8760                                 goto error;
8761                 }
8762
8763                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8764                 {
8765                         if (!p->texture_reflection)
8766                                 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);
8767                         if (!p->texture_reflection)
8768                                 goto error;
8769                 }
8770         }
8771
8772         // render views
8773         r_refdef.view = originalview;
8774         r_refdef.view.showdebug = false;
8775         r_refdef.view.width = r_waterstate.waterwidth;
8776         r_refdef.view.height = r_waterstate.waterheight;
8777         r_refdef.view.useclipplane = true;
8778         myview = r_refdef.view;
8779         r_waterstate.renderingscene = true;
8780         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8781         {
8782                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8783                 {
8784                         r_refdef.view = myview;
8785                         if(r_water_scissormode.integer)
8786                         {
8787                                 R_SetupView(true);
8788                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8789                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8790                         }
8791
8792                         // render reflected scene and copy into texture
8793                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8794                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8795                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8796                         r_refdef.view.clipplane = p->plane;
8797
8798                         // reverse the cullface settings for this render
8799                         r_refdef.view.cullface_front = GL_FRONT;
8800                         r_refdef.view.cullface_back = GL_BACK;
8801                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8802                         {
8803                                 r_refdef.view.usecustompvs = true;
8804                                 if (p->pvsvalid)
8805                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8806                                 else
8807                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8808                         }
8809
8810                         R_ResetViewRendering3D();
8811                         R_ClearScreen(r_refdef.fogenabled);
8812                         if(r_water_scissormode.integer & 2)
8813                                 R_View_UpdateWithScissor(myscissor);
8814                         else
8815                                 R_View_Update();
8816                         if(r_water_scissormode.integer & 1)
8817                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8818                         R_RenderScene();
8819
8820                         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);
8821                 }
8822
8823                 // render the normal view scene and copy into texture
8824                 // (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)
8825                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8826                 {
8827                         r_refdef.view = myview;
8828                         if(r_water_scissormode.integer)
8829                         {
8830                                 R_SetupView(true);
8831                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8832                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8833                         }
8834
8835                         r_waterstate.renderingrefraction = true;
8836
8837                         r_refdef.view.clipplane = p->plane;
8838                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8839                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8840
8841                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8842                         {
8843                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8844                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8845                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8846                                 R_RenderView_UpdateViewVectors();
8847                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8848                                 {
8849                                         r_refdef.view.usecustompvs = true;
8850                                         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);
8851                                 }
8852                         }
8853
8854                         PlaneClassify(&r_refdef.view.clipplane);
8855
8856                         R_ResetViewRendering3D();
8857                         R_ClearScreen(r_refdef.fogenabled);
8858                         if(r_water_scissormode.integer & 2)
8859                                 R_View_UpdateWithScissor(myscissor);
8860                         else
8861                                 R_View_Update();
8862                         if(r_water_scissormode.integer & 1)
8863                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8864                         R_RenderScene();
8865
8866                         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);
8867                         r_waterstate.renderingrefraction = false;
8868                 }
8869                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8870                 {
8871                         r_refdef.view = myview;
8872
8873                         r_refdef.view.clipplane = p->plane;
8874                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8875                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8876
8877                         r_refdef.view.width = r_waterstate.camerawidth;
8878                         r_refdef.view.height = r_waterstate.cameraheight;
8879                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8880                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8881
8882                         if(p->camera_entity)
8883                         {
8884                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8885                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8886                         }
8887
8888                         // note: all of the view is used for displaying... so
8889                         // there is no use in scissoring
8890
8891                         // reverse the cullface settings for this render
8892                         r_refdef.view.cullface_front = GL_FRONT;
8893                         r_refdef.view.cullface_back = GL_BACK;
8894                         // also reverse the view matrix
8895                         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
8896                         R_RenderView_UpdateViewVectors();
8897                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8898                         {
8899                                 r_refdef.view.usecustompvs = true;
8900                                 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);
8901                         }
8902                         
8903                         // camera needs no clipplane
8904                         r_refdef.view.useclipplane = false;
8905
8906                         PlaneClassify(&r_refdef.view.clipplane);
8907
8908                         R_ResetViewRendering3D();
8909                         R_ClearScreen(r_refdef.fogenabled);
8910                         R_View_Update();
8911                         R_RenderScene();
8912
8913                         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);
8914                         r_waterstate.renderingrefraction = false;
8915                 }
8916
8917         }
8918         r_waterstate.renderingscene = false;
8919         r_refdef.view = originalview;
8920         R_ResetViewRendering3D();
8921         R_ClearScreen(r_refdef.fogenabled);
8922         R_View_Update();
8923         return;
8924 error:
8925         r_refdef.view = originalview;
8926         r_waterstate.renderingscene = false;
8927         Cvar_SetValueQuick(&r_water, 0);
8928         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8929         return;
8930 }
8931
8932 void R_Bloom_StartFrame(void)
8933 {
8934         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8935
8936         switch(vid.renderpath)
8937         {
8938         case RENDERPATH_GL20:
8939         case RENDERPATH_CGGL:
8940         case RENDERPATH_D3D9:
8941         case RENDERPATH_D3D10:
8942         case RENDERPATH_D3D11:
8943                 break;
8944         case RENDERPATH_GL13:
8945         case RENDERPATH_GL11:
8946                 return;
8947         }
8948
8949         // set bloomwidth and bloomheight to the bloom resolution that will be
8950         // used (often less than the screen resolution for faster rendering)
8951         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8952         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8953         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8954         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8955         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8956
8957         // calculate desired texture sizes
8958         if (vid.support.arb_texture_non_power_of_two)
8959         {
8960                 screentexturewidth = r_refdef.view.width;
8961                 screentextureheight = r_refdef.view.height;
8962                 bloomtexturewidth = r_bloomstate.bloomwidth;
8963                 bloomtextureheight = r_bloomstate.bloomheight;
8964         }
8965         else
8966         {
8967                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8968                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8969                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8970                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8971         }
8972
8973         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))
8974         {
8975                 Cvar_SetValueQuick(&r_hdr, 0);
8976                 Cvar_SetValueQuick(&r_bloom, 0);
8977                 Cvar_SetValueQuick(&r_motionblur, 0);
8978                 Cvar_SetValueQuick(&r_damageblur, 0);
8979         }
8980
8981         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)))
8982                 screentexturewidth = screentextureheight = 0;
8983         if (!r_hdr.integer && !r_bloom.integer)
8984                 bloomtexturewidth = bloomtextureheight = 0;
8985
8986         // allocate textures as needed
8987         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8988         {
8989                 if (r_bloomstate.texture_screen)
8990                         R_FreeTexture(r_bloomstate.texture_screen);
8991                 r_bloomstate.texture_screen = NULL;
8992                 r_bloomstate.screentexturewidth = screentexturewidth;
8993                 r_bloomstate.screentextureheight = screentextureheight;
8994                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8995                         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);
8996         }
8997         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8998         {
8999                 if (r_bloomstate.texture_bloom)
9000                         R_FreeTexture(r_bloomstate.texture_bloom);
9001                 r_bloomstate.texture_bloom = NULL;
9002                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9003                 r_bloomstate.bloomtextureheight = bloomtextureheight;
9004                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9005                         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);
9006         }
9007
9008         // when doing a reduced render (HDR) we want to use a smaller area
9009         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9010         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9011         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9012         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9013         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9014
9015         // set up a texcoord array for the full resolution screen image
9016         // (we have to keep this around to copy back during final render)
9017         r_bloomstate.screentexcoord2f[0] = 0;
9018         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9019         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9020         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9021         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9022         r_bloomstate.screentexcoord2f[5] = 0;
9023         r_bloomstate.screentexcoord2f[6] = 0;
9024         r_bloomstate.screentexcoord2f[7] = 0;
9025
9026         // set up a texcoord array for the reduced resolution bloom image
9027         // (which will be additive blended over the screen image)
9028         r_bloomstate.bloomtexcoord2f[0] = 0;
9029         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9030         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9031         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9032         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9033         r_bloomstate.bloomtexcoord2f[5] = 0;
9034         r_bloomstate.bloomtexcoord2f[6] = 0;
9035         r_bloomstate.bloomtexcoord2f[7] = 0;
9036
9037         switch(vid.renderpath)
9038         {
9039         case RENDERPATH_GL11:
9040         case RENDERPATH_GL13:
9041         case RENDERPATH_GL20:
9042         case RENDERPATH_CGGL:
9043                 break;
9044         case RENDERPATH_D3D9:
9045         case RENDERPATH_D3D10:
9046         case RENDERPATH_D3D11:
9047                 {
9048                         int i;
9049                         for (i = 0;i < 4;i++)
9050                         {
9051                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9052                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9053                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9054                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9055                         }
9056                 }
9057                 break;
9058         }
9059
9060         if (r_hdr.integer || r_bloom.integer)
9061         {
9062                 r_bloomstate.enabled = true;
9063                 r_bloomstate.hdr = r_hdr.integer != 0;
9064         }
9065
9066         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);
9067 }
9068
9069 void R_Bloom_CopyBloomTexture(float colorscale)
9070 {
9071         r_refdef.stats.bloom++;
9072
9073         // scale down screen texture to the bloom texture size
9074         CHECKGLERROR
9075         R_SetViewport(&r_bloomstate.viewport);
9076         GL_BlendFunc(GL_ONE, GL_ZERO);
9077         GL_Color(colorscale, colorscale, colorscale, 1);
9078         // 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...
9079         switch(vid.renderpath)
9080         {
9081         case RENDERPATH_GL11:
9082         case RENDERPATH_GL13:
9083         case RENDERPATH_GL20:
9084         case RENDERPATH_CGGL:
9085                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9086                 break;
9087         case RENDERPATH_D3D9:
9088         case RENDERPATH_D3D10:
9089         case RENDERPATH_D3D11:
9090                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9091                 break;
9092         }
9093         // TODO: do boxfilter scale-down in shader?
9094         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9095         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9096         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9097
9098         // we now have a bloom image in the framebuffer
9099         // copy it into the bloom image texture for later processing
9100         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);
9101         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9102 }
9103
9104 void R_Bloom_CopyHDRTexture(void)
9105 {
9106         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);
9107         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9108 }
9109
9110 void R_Bloom_MakeTexture(void)
9111 {
9112         int x, range, dir;
9113         float xoffset, yoffset, r, brighten;
9114
9115         r_refdef.stats.bloom++;
9116
9117         R_ResetViewRendering2D();
9118
9119         // we have a bloom image in the framebuffer
9120         CHECKGLERROR
9121         R_SetViewport(&r_bloomstate.viewport);
9122
9123         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9124         {
9125                 x *= 2;
9126                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9127                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9128                 GL_Color(r,r,r,1);
9129                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9130                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9131                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9132                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9133
9134                 // copy the vertically blurred bloom view to a texture
9135                 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);
9136                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9137         }
9138
9139         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9140         brighten = r_bloom_brighten.value;
9141         if (r_hdr.integer)
9142                 brighten *= r_hdr_range.value;
9143         brighten = sqrt(brighten);
9144         if(range >= 1)
9145                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9146         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9147
9148         for (dir = 0;dir < 2;dir++)
9149         {
9150                 // blend on at multiple vertical offsets to achieve a vertical blur
9151                 // TODO: do offset blends using GLSL
9152                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9153                 GL_BlendFunc(GL_ONE, GL_ZERO);
9154                 for (x = -range;x <= range;x++)
9155                 {
9156                         if (!dir){xoffset = 0;yoffset = x;}
9157                         else {xoffset = x;yoffset = 0;}
9158                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9159                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9160                         // compute a texcoord array with the specified x and y offset
9161                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9162                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9163                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9164                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9165                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9166                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9167                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9168                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9169                         // this r value looks like a 'dot' particle, fading sharply to
9170                         // black at the edges
9171                         // (probably not realistic but looks good enough)
9172                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9173                         //r = brighten/(range*2+1);
9174                         r = brighten / (range * 2 + 1);
9175                         if(range >= 1)
9176                                 r *= (1 - x*x/(float)(range*range));
9177                         GL_Color(r, r, r, 1);
9178                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9179                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9180                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9181                         GL_BlendFunc(GL_ONE, GL_ONE);
9182                 }
9183
9184                 // copy the vertically blurred bloom view to a texture
9185                 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);
9186                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9187         }
9188 }
9189
9190 void R_HDR_RenderBloomTexture(void)
9191 {
9192         int oldwidth, oldheight;
9193         float oldcolorscale;
9194         int oldwaterstate;
9195
9196         oldwaterstate = r_waterstate.enabled;
9197         oldcolorscale = r_refdef.view.colorscale;
9198         oldwidth = r_refdef.view.width;
9199         oldheight = r_refdef.view.height;
9200         r_refdef.view.width = r_bloomstate.bloomwidth;
9201         r_refdef.view.height = r_bloomstate.bloomheight;
9202
9203         if(r_hdr.integer < 2)
9204                 r_waterstate.enabled = false;
9205
9206         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9207         // TODO: add exposure compensation features
9208         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9209
9210         r_refdef.view.showdebug = false;
9211         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9212
9213         R_ResetViewRendering3D();
9214
9215         R_ClearScreen(r_refdef.fogenabled);
9216         if (r_timereport_active)
9217                 R_TimeReport("HDRclear");
9218
9219         R_View_Update();
9220         if (r_timereport_active)
9221                 R_TimeReport("visibility");
9222
9223         // only do secondary renders with HDR if r_hdr is 2 or higher
9224         r_waterstate.numwaterplanes = 0;
9225         if (r_waterstate.enabled)
9226                 R_RenderWaterPlanes();
9227
9228         r_refdef.view.showdebug = true;
9229         R_RenderScene();
9230         r_waterstate.numwaterplanes = 0;
9231
9232         R_ResetViewRendering2D();
9233
9234         R_Bloom_CopyHDRTexture();
9235         R_Bloom_MakeTexture();
9236
9237         // restore the view settings
9238         r_waterstate.enabled = oldwaterstate;
9239         r_refdef.view.width = oldwidth;
9240         r_refdef.view.height = oldheight;
9241         r_refdef.view.colorscale = oldcolorscale;
9242
9243         R_ResetViewRendering3D();
9244
9245         R_ClearScreen(r_refdef.fogenabled);
9246         if (r_timereport_active)
9247                 R_TimeReport("viewclear");
9248 }
9249
9250 static void R_BlendView(void)
9251 {
9252         unsigned int permutation;
9253         float uservecs[4][4];
9254
9255         switch (vid.renderpath)
9256         {
9257         case RENDERPATH_GL20:
9258         case RENDERPATH_CGGL:
9259         case RENDERPATH_D3D9:
9260         case RENDERPATH_D3D10:
9261         case RENDERPATH_D3D11:
9262                 permutation =
9263                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9264                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9265                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9266                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9267                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9268
9269                 if (r_bloomstate.texture_screen)
9270                 {
9271                         // make sure the buffer is available
9272                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9273
9274                         R_ResetViewRendering2D();
9275
9276                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9277                         {
9278                                 // declare variables
9279                                 float speed;
9280                                 static float avgspeed;
9281
9282                                 speed = VectorLength(cl.movement_velocity);
9283
9284                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9285                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9286
9287                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9288                                 speed = bound(0, speed, 1);
9289                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9290
9291                                 // calculate values into a standard alpha
9292                                 cl.motionbluralpha = 1 - exp(-
9293                                                 (
9294                                                  (r_motionblur.value * speed / 80)
9295                                                  +
9296                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9297                                                 )
9298                                                 /
9299                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9300                                            );
9301
9302                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9303                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9304                                 // apply the blur
9305                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9306                                 {
9307                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9308                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9309                                         switch(vid.renderpath)
9310                                         {
9311                                         case RENDERPATH_GL11:
9312                                         case RENDERPATH_GL13:
9313                                         case RENDERPATH_GL20:
9314                                         case RENDERPATH_CGGL:
9315                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9316                                                 break;
9317                                         case RENDERPATH_D3D9:
9318                                         case RENDERPATH_D3D10:
9319                                         case RENDERPATH_D3D11:
9320                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9321                                                 break;
9322                                         }
9323                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9324                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9325                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9326                                 }
9327                         }
9328
9329                         // copy view into the screen texture
9330                         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);
9331                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9332                 }
9333                 else if (!r_bloomstate.texture_bloom)
9334                 {
9335                         // we may still have to do view tint...
9336                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9337                         {
9338                                 // apply a color tint to the whole view
9339                                 R_ResetViewRendering2D();
9340                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9341                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9342                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9343                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9344                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9345                         }
9346                         break; // no screen processing, no bloom, skip it
9347                 }
9348
9349                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9350                 {
9351                         // render simple bloom effect
9352                         // copy the screen and shrink it and darken it for the bloom process
9353                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9354                         // make the bloom texture
9355                         R_Bloom_MakeTexture();
9356                 }
9357
9358 #if _MSC_VER >= 1400
9359 #define sscanf sscanf_s
9360 #endif
9361                 memset(uservecs, 0, sizeof(uservecs));
9362                 if (r_glsl_postprocess_uservec1_enable.integer)
9363                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9364                 if (r_glsl_postprocess_uservec2_enable.integer)
9365                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9366                 if (r_glsl_postprocess_uservec3_enable.integer)
9367                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9368                 if (r_glsl_postprocess_uservec4_enable.integer)
9369                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9370
9371                 R_ResetViewRendering2D();
9372                 GL_Color(1, 1, 1, 1);
9373                 GL_BlendFunc(GL_ONE, GL_ZERO);
9374
9375                 switch(vid.renderpath)
9376                 {
9377                 case RENDERPATH_GL20:
9378                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9379                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9380                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9381                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9382                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9383                         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]);
9384                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9385                         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]);
9386                         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]);
9387                         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]);
9388                         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]);
9389                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9390                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9391                         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);
9392                         break;
9393                 case RENDERPATH_CGGL:
9394 #ifdef SUPPORTCG
9395                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9396                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9397                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9398                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9399                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9400                         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
9401                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9402                         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
9403                         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
9404                         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
9405                         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
9406                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9407                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9408                         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);
9409 #endif
9410                         break;
9411                 case RENDERPATH_D3D9:
9412 #ifdef SUPPORTD3D
9413                         // 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...
9414                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9415                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9416                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9417                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9418                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9419                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9420                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9421                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9422                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9423                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9424                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9425                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9426                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9427                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9428 #endif
9429                         break;
9430                 case RENDERPATH_D3D10:
9431                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9432                         break;
9433                 case RENDERPATH_D3D11:
9434                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9435                         break;
9436                 default:
9437                         break;
9438                 }
9439                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9440                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9441                 break;
9442         case RENDERPATH_GL13:
9443         case RENDERPATH_GL11:
9444                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9445                 {
9446                         // apply a color tint to the whole view
9447                         R_ResetViewRendering2D();
9448                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9449                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9450                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9451                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9452                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9453                 }
9454                 break;
9455         }
9456 }
9457
9458 matrix4x4_t r_waterscrollmatrix;
9459
9460 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9461 {
9462         if (r_refdef.fog_density)
9463         {
9464                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9465                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9466                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9467
9468                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9469                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9470                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9471                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9472
9473                 {
9474                         vec3_t fogvec;
9475                         VectorCopy(r_refdef.fogcolor, fogvec);
9476                         //   color.rgb *= ContrastBoost * SceneBrightness;
9477                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9478                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9479                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9480                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9481                 }
9482         }
9483 }
9484
9485 void R_UpdateVariables(void)
9486 {
9487         R_Textures_Frame();
9488
9489         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9490
9491         r_refdef.farclip = r_farclip_base.value;
9492         if (r_refdef.scene.worldmodel)
9493                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9494         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9495
9496         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9497                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9498         r_refdef.polygonfactor = 0;
9499         r_refdef.polygonoffset = 0;
9500         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9501         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9502
9503         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9504         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9505         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9506         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9507         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9508         if (FAKELIGHT_ENABLED)
9509         {
9510                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9511         }
9512         if (r_showsurfaces.integer)
9513         {
9514                 r_refdef.scene.rtworld = false;
9515                 r_refdef.scene.rtworldshadows = false;
9516                 r_refdef.scene.rtdlight = false;
9517                 r_refdef.scene.rtdlightshadows = false;
9518                 r_refdef.lightmapintensity = 0;
9519         }
9520
9521         if (gamemode == GAME_NEHAHRA)
9522         {
9523                 if (gl_fogenable.integer)
9524                 {
9525                         r_refdef.oldgl_fogenable = true;
9526                         r_refdef.fog_density = gl_fogdensity.value;
9527                         r_refdef.fog_red = gl_fogred.value;
9528                         r_refdef.fog_green = gl_foggreen.value;
9529                         r_refdef.fog_blue = gl_fogblue.value;
9530                         r_refdef.fog_alpha = 1;
9531                         r_refdef.fog_start = 0;
9532                         r_refdef.fog_end = gl_skyclip.value;
9533                         r_refdef.fog_height = 1<<30;
9534                         r_refdef.fog_fadedepth = 128;
9535                 }
9536                 else if (r_refdef.oldgl_fogenable)
9537                 {
9538                         r_refdef.oldgl_fogenable = false;
9539                         r_refdef.fog_density = 0;
9540                         r_refdef.fog_red = 0;
9541                         r_refdef.fog_green = 0;
9542                         r_refdef.fog_blue = 0;
9543                         r_refdef.fog_alpha = 0;
9544                         r_refdef.fog_start = 0;
9545                         r_refdef.fog_end = 0;
9546                         r_refdef.fog_height = 1<<30;
9547                         r_refdef.fog_fadedepth = 128;
9548                 }
9549         }
9550
9551         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9552         r_refdef.fog_start = max(0, r_refdef.fog_start);
9553         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9554
9555         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9556
9557         if (r_refdef.fog_density && r_drawfog.integer)
9558         {
9559                 r_refdef.fogenabled = true;
9560                 // this is the point where the fog reaches 0.9986 alpha, which we
9561                 // consider a good enough cutoff point for the texture
9562                 // (0.9986 * 256 == 255.6)
9563                 if (r_fog_exp2.integer)
9564                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9565                 else
9566                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9567                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9568                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9569                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9570                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9571                         R_BuildFogHeightTexture();
9572                 // fog color was already set
9573                 // update the fog texture
9574                 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)
9575                         R_BuildFogTexture();
9576                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9577                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9578         }
9579         else
9580                 r_refdef.fogenabled = false;
9581
9582         switch(vid.renderpath)
9583         {
9584         case RENDERPATH_GL20:
9585         case RENDERPATH_CGGL:
9586         case RENDERPATH_D3D9:
9587         case RENDERPATH_D3D10:
9588         case RENDERPATH_D3D11:
9589                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9590                 {
9591                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9592                         {
9593                                 // build GLSL gamma texture
9594 #define RAMPWIDTH 256
9595                                 unsigned short ramp[RAMPWIDTH * 3];
9596                                 unsigned char rampbgr[RAMPWIDTH][4];
9597                                 int i;
9598
9599                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9600
9601                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9602                                 for(i = 0; i < RAMPWIDTH; ++i)
9603                                 {
9604                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9605                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9606                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9607                                         rampbgr[i][3] = 0;
9608                                 }
9609                                 if (r_texture_gammaramps)
9610                                 {
9611                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9612                                 }
9613                                 else
9614                                 {
9615                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9616                                 }
9617                         }
9618                 }
9619                 else
9620                 {
9621                         // remove GLSL gamma texture
9622                 }
9623                 break;
9624         case RENDERPATH_GL13:
9625         case RENDERPATH_GL11:
9626                 break;
9627         }
9628 }
9629
9630 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9631 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9632 /*
9633 ================
9634 R_SelectScene
9635 ================
9636 */
9637 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9638         if( scenetype != r_currentscenetype ) {
9639                 // store the old scenetype
9640                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9641                 r_currentscenetype = scenetype;
9642                 // move in the new scene
9643                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9644         }
9645 }
9646
9647 /*
9648 ================
9649 R_GetScenePointer
9650 ================
9651 */
9652 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9653 {
9654         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9655         if( scenetype == r_currentscenetype ) {
9656                 return &r_refdef.scene;
9657         } else {
9658                 return &r_scenes_store[ scenetype ];
9659         }
9660 }
9661
9662 /*
9663 ================
9664 R_RenderView
9665 ================
9666 */
9667 void R_RenderView(void)
9668 {
9669         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9670         if (r_timereport_active)
9671                 R_TimeReport("start");
9672         r_textureframe++; // used only by R_GetCurrentTexture
9673         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9674
9675         if(R_CompileShader_CheckStaticParms())
9676                 R_GLSL_Restart_f();
9677
9678         if (!r_drawentities.integer)
9679                 r_refdef.scene.numentities = 0;
9680
9681         R_AnimCache_ClearCache();
9682         R_FrameData_NewFrame();
9683
9684         /* adjust for stereo display */
9685         if(R_Stereo_Active())
9686         {
9687                 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);
9688                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9689         }
9690
9691         if (r_refdef.view.isoverlay)
9692         {
9693                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9694                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9695                 R_TimeReport("depthclear");
9696
9697                 r_refdef.view.showdebug = false;
9698
9699                 r_waterstate.enabled = false;
9700                 r_waterstate.numwaterplanes = 0;
9701
9702                 R_RenderScene();
9703
9704                 r_refdef.view.matrix = originalmatrix;
9705
9706                 CHECKGLERROR
9707                 return;
9708         }
9709
9710         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9711         {
9712                 r_refdef.view.matrix = originalmatrix;
9713                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9714         }
9715
9716         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9717
9718         R_RenderView_UpdateViewVectors();
9719
9720         R_Shadow_UpdateWorldLightSelection();
9721
9722         R_Bloom_StartFrame();
9723         R_Water_StartFrame();
9724
9725         CHECKGLERROR
9726         if (r_timereport_active)
9727                 R_TimeReport("viewsetup");
9728
9729         R_ResetViewRendering3D();
9730
9731         if (r_refdef.view.clear || r_refdef.fogenabled)
9732         {
9733                 R_ClearScreen(r_refdef.fogenabled);
9734                 if (r_timereport_active)
9735                         R_TimeReport("viewclear");
9736         }
9737         r_refdef.view.clear = true;
9738
9739         // this produces a bloom texture to be used in R_BlendView() later
9740         if (r_hdr.integer && r_bloomstate.bloomwidth)
9741         {
9742                 R_HDR_RenderBloomTexture();
9743                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9744                 r_textureframe++; // used only by R_GetCurrentTexture
9745         }
9746
9747         r_refdef.view.showdebug = true;
9748
9749         R_View_Update();
9750         if (r_timereport_active)
9751                 R_TimeReport("visibility");
9752
9753         r_waterstate.numwaterplanes = 0;
9754         if (r_waterstate.enabled)
9755                 R_RenderWaterPlanes();
9756
9757         R_RenderScene();
9758         r_waterstate.numwaterplanes = 0;
9759
9760         R_BlendView();
9761         if (r_timereport_active)
9762                 R_TimeReport("blendview");
9763
9764         GL_Scissor(0, 0, vid.width, vid.height);
9765         GL_ScissorTest(false);
9766
9767         r_refdef.view.matrix = originalmatrix;
9768
9769         CHECKGLERROR
9770 }
9771
9772 void R_RenderWaterPlanes(void)
9773 {
9774         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9775         {
9776                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9777                 if (r_timereport_active)
9778                         R_TimeReport("waterworld");
9779         }
9780
9781         // don't let sound skip if going slow
9782         if (r_refdef.scene.extraupdate)
9783                 S_ExtraUpdate ();
9784
9785         R_DrawModelsAddWaterPlanes();
9786         if (r_timereport_active)
9787                 R_TimeReport("watermodels");
9788
9789         if (r_waterstate.numwaterplanes)
9790         {
9791                 R_Water_ProcessPlanes();
9792                 if (r_timereport_active)
9793                         R_TimeReport("waterscenes");
9794         }
9795 }
9796
9797 extern void R_DrawLightningBeams (void);
9798 extern void VM_CL_AddPolygonsToMeshQueue (void);
9799 extern void R_DrawPortals (void);
9800 extern cvar_t cl_locs_show;
9801 static void R_DrawLocs(void);
9802 static void R_DrawEntityBBoxes(void);
9803 static void R_DrawModelDecals(void);
9804 extern void R_DrawModelShadows(void);
9805 extern void R_DrawModelShadowMaps(void);
9806 extern cvar_t cl_decals_newsystem;
9807 extern qboolean r_shadow_usingdeferredprepass;
9808 void R_RenderScene(void)
9809 {
9810         qboolean shadowmapping = false;
9811
9812         if (r_timereport_active)
9813                 R_TimeReport("beginscene");
9814
9815         r_refdef.stats.renders++;
9816
9817         R_UpdateFogColor();
9818
9819         // don't let sound skip if going slow
9820         if (r_refdef.scene.extraupdate)
9821                 S_ExtraUpdate ();
9822
9823         R_MeshQueue_BeginScene();
9824
9825         R_SkyStartFrame();
9826
9827         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);
9828
9829         if (r_timereport_active)
9830                 R_TimeReport("skystartframe");
9831
9832         if (cl.csqc_vidvars.drawworld)
9833         {
9834                 // don't let sound skip if going slow
9835                 if (r_refdef.scene.extraupdate)
9836                         S_ExtraUpdate ();
9837
9838                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9839                 {
9840                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9841                         if (r_timereport_active)
9842                                 R_TimeReport("worldsky");
9843                 }
9844
9845                 if (R_DrawBrushModelsSky() && r_timereport_active)
9846                         R_TimeReport("bmodelsky");
9847
9848                 if (skyrendermasked && skyrenderlater)
9849                 {
9850                         // we have to force off the water clipping plane while rendering sky
9851                         R_SetupView(false);
9852                         R_Sky();
9853                         R_SetupView(true);
9854                         if (r_timereport_active)
9855                                 R_TimeReport("sky");
9856                 }
9857         }
9858
9859         R_AnimCache_CacheVisibleEntities();
9860         if (r_timereport_active)
9861                 R_TimeReport("animation");
9862
9863         R_Shadow_PrepareLights();
9864         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9865                 R_Shadow_PrepareModelShadows();
9866         if (r_timereport_active)
9867                 R_TimeReport("preparelights");
9868
9869         if (R_Shadow_ShadowMappingEnabled())
9870                 shadowmapping = true;
9871
9872         if (r_shadow_usingdeferredprepass)
9873                 R_Shadow_DrawPrepass();
9874
9875         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9876         {
9877                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9878                 if (r_timereport_active)
9879                         R_TimeReport("worlddepth");
9880         }
9881         if (r_depthfirst.integer >= 2)
9882         {
9883                 R_DrawModelsDepth();
9884                 if (r_timereport_active)
9885                         R_TimeReport("modeldepth");
9886         }
9887
9888         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9889         {
9890                 R_DrawModelShadowMaps();
9891                 R_ResetViewRendering3D();
9892                 // don't let sound skip if going slow
9893                 if (r_refdef.scene.extraupdate)
9894                         S_ExtraUpdate ();
9895         }
9896
9897         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9898         {
9899                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9900                 if (r_timereport_active)
9901                         R_TimeReport("world");
9902         }
9903
9904         // don't let sound skip if going slow
9905         if (r_refdef.scene.extraupdate)
9906                 S_ExtraUpdate ();
9907
9908         R_DrawModels();
9909         if (r_timereport_active)
9910                 R_TimeReport("models");
9911
9912         // don't let sound skip if going slow
9913         if (r_refdef.scene.extraupdate)
9914                 S_ExtraUpdate ();
9915
9916         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9917         {
9918                 R_DrawModelShadows();
9919                 R_ResetViewRendering3D();
9920                 // don't let sound skip if going slow
9921                 if (r_refdef.scene.extraupdate)
9922                         S_ExtraUpdate ();
9923         }
9924
9925         if (!r_shadow_usingdeferredprepass)
9926         {
9927                 R_Shadow_DrawLights();
9928                 if (r_timereport_active)
9929                         R_TimeReport("rtlights");
9930         }
9931
9932         // don't let sound skip if going slow
9933         if (r_refdef.scene.extraupdate)
9934                 S_ExtraUpdate ();
9935
9936         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9937         {
9938                 R_DrawModelShadows();
9939                 R_ResetViewRendering3D();
9940                 // don't let sound skip if going slow
9941                 if (r_refdef.scene.extraupdate)
9942                         S_ExtraUpdate ();
9943         }
9944
9945         if (cl.csqc_vidvars.drawworld)
9946         {
9947                 if (cl_decals_newsystem.integer)
9948                 {
9949                         R_DrawModelDecals();
9950                         if (r_timereport_active)
9951                                 R_TimeReport("modeldecals");
9952                 }
9953                 else
9954                 {
9955                         R_DrawDecals();
9956                         if (r_timereport_active)
9957                                 R_TimeReport("decals");
9958                 }
9959
9960                 R_DrawParticles();
9961                 if (r_timereport_active)
9962                         R_TimeReport("particles");
9963
9964                 R_DrawExplosions();
9965                 if (r_timereport_active)
9966                         R_TimeReport("explosions");
9967
9968                 R_DrawLightningBeams();
9969                 if (r_timereport_active)
9970                         R_TimeReport("lightning");
9971         }
9972
9973         VM_CL_AddPolygonsToMeshQueue();
9974
9975         if (r_refdef.view.showdebug)
9976         {
9977                 if (cl_locs_show.integer)
9978                 {
9979                         R_DrawLocs();
9980                         if (r_timereport_active)
9981                                 R_TimeReport("showlocs");
9982                 }
9983
9984                 if (r_drawportals.integer)
9985                 {
9986                         R_DrawPortals();
9987                         if (r_timereport_active)
9988                                 R_TimeReport("portals");
9989                 }
9990
9991                 if (r_showbboxes.value > 0)
9992                 {
9993                         R_DrawEntityBBoxes();
9994                         if (r_timereport_active)
9995                                 R_TimeReport("bboxes");
9996                 }
9997         }
9998
9999         R_MeshQueue_RenderTransparent();
10000         if (r_timereport_active)
10001                 R_TimeReport("drawtrans");
10002
10003         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))
10004         {
10005                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10006                 if (r_timereport_active)
10007                         R_TimeReport("worlddebug");
10008                 R_DrawModelsDebug();
10009                 if (r_timereport_active)
10010                         R_TimeReport("modeldebug");
10011         }
10012
10013         if (cl.csqc_vidvars.drawworld)
10014         {
10015                 R_Shadow_DrawCoronas();
10016                 if (r_timereport_active)
10017                         R_TimeReport("coronas");
10018         }
10019
10020 #if 0
10021         {
10022                 GL_DepthTest(false);
10023                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10024                 GL_Color(1, 1, 1, 1);
10025                 qglBegin(GL_POLYGON);
10026                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10027                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10028                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10029                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10030                 qglEnd();
10031                 qglBegin(GL_POLYGON);
10032                 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]);
10033                 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]);
10034                 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]);
10035                 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]);
10036                 qglEnd();
10037                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10038         }
10039 #endif
10040
10041         // don't let sound skip if going slow
10042         if (r_refdef.scene.extraupdate)
10043                 S_ExtraUpdate ();
10044
10045         R_ResetViewRendering2D();
10046 }
10047
10048 static const unsigned short bboxelements[36] =
10049 {
10050         5, 1, 3, 5, 3, 7,
10051         6, 2, 0, 6, 0, 4,
10052         7, 3, 2, 7, 2, 6,
10053         4, 0, 1, 4, 1, 5,
10054         4, 5, 7, 4, 7, 6,
10055         1, 0, 2, 1, 2, 3,
10056 };
10057
10058 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10059 {
10060         int i;
10061         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10062
10063         RSurf_ActiveWorldEntity();
10064
10065         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10066         GL_DepthMask(false);
10067         GL_DepthRange(0, 1);
10068         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10069 //      R_Mesh_ResetTextureState();
10070
10071         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10072         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10073         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10074         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10075         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10076         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10077         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10078         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10079         R_FillColors(color4f, 8, cr, cg, cb, ca);
10080         if (r_refdef.fogenabled)
10081         {
10082                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10083                 {
10084                         f1 = RSurf_FogVertex(v);
10085                         f2 = 1 - f1;
10086                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10087                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10088                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10089                 }
10090         }
10091         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10092         R_Mesh_ResetTextureState();
10093         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10094         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10095 }
10096
10097 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10098 {
10099         int i;
10100         float color[4];
10101         prvm_edict_t *edict;
10102         prvm_prog_t *prog_save = prog;
10103
10104         // this function draws bounding boxes of server entities
10105         if (!sv.active)
10106                 return;
10107
10108         GL_CullFace(GL_NONE);
10109         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10110
10111         prog = 0;
10112         SV_VM_Begin();
10113         for (i = 0;i < numsurfaces;i++)
10114         {
10115                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10116                 switch ((int)edict->fields.server->solid)
10117                 {
10118                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10119                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10120                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10121                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10122                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10123                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10124                 }
10125                 color[3] *= r_showbboxes.value;
10126                 color[3] = bound(0, color[3], 1);
10127                 GL_DepthTest(!r_showdisabledepthtest.integer);
10128                 GL_CullFace(r_refdef.view.cullface_front);
10129                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10130         }
10131         SV_VM_End();
10132         prog = prog_save;
10133 }
10134
10135 static void R_DrawEntityBBoxes(void)
10136 {
10137         int i;
10138         prvm_edict_t *edict;
10139         vec3_t center;
10140         prvm_prog_t *prog_save = prog;
10141
10142         // this function draws bounding boxes of server entities
10143         if (!sv.active)
10144                 return;
10145
10146         prog = 0;
10147         SV_VM_Begin();
10148         for (i = 0;i < prog->num_edicts;i++)
10149         {
10150                 edict = PRVM_EDICT_NUM(i);
10151                 if (edict->priv.server->free)
10152                         continue;
10153                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10154                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10155                         continue;
10156                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10157                         continue;
10158                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10159                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10160         }
10161         SV_VM_End();
10162         prog = prog_save;
10163 }
10164
10165 static const int nomodelelement3i[24] =
10166 {
10167         5, 2, 0,
10168         5, 1, 2,
10169         5, 0, 3,
10170         5, 3, 1,
10171         0, 2, 4,
10172         2, 1, 4,
10173         3, 0, 4,
10174         1, 3, 4
10175 };
10176
10177 static const unsigned short nomodelelement3s[24] =
10178 {
10179         5, 2, 0,
10180         5, 1, 2,
10181         5, 0, 3,
10182         5, 3, 1,
10183         0, 2, 4,
10184         2, 1, 4,
10185         3, 0, 4,
10186         1, 3, 4
10187 };
10188
10189 static const float nomodelvertex3f[6*3] =
10190 {
10191         -16,   0,   0,
10192          16,   0,   0,
10193           0, -16,   0,
10194           0,  16,   0,
10195           0,   0, -16,
10196           0,   0,  16
10197 };
10198
10199 static const float nomodelcolor4f[6*4] =
10200 {
10201         0.0f, 0.0f, 0.5f, 1.0f,
10202         0.0f, 0.0f, 0.5f, 1.0f,
10203         0.0f, 0.5f, 0.0f, 1.0f,
10204         0.0f, 0.5f, 0.0f, 1.0f,
10205         0.5f, 0.0f, 0.0f, 1.0f,
10206         0.5f, 0.0f, 0.0f, 1.0f
10207 };
10208
10209 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10210 {
10211         int i;
10212         float f1, f2, *c;
10213         float color4f[6*4];
10214
10215         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);
10216
10217         // this is only called once per entity so numsurfaces is always 1, and
10218         // surfacelist is always {0}, so this code does not handle batches
10219
10220         if (rsurface.ent_flags & RENDER_ADDITIVE)
10221         {
10222                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10223                 GL_DepthMask(false);
10224         }
10225         else if (rsurface.colormod[3] < 1)
10226         {
10227                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10228                 GL_DepthMask(false);
10229         }
10230         else
10231         {
10232                 GL_BlendFunc(GL_ONE, GL_ZERO);
10233                 GL_DepthMask(true);
10234         }
10235         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10236         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10237         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10238         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10239         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10240         for (i = 0, c = color4f;i < 6;i++, c += 4)
10241         {
10242                 c[0] *= rsurface.colormod[0];
10243                 c[1] *= rsurface.colormod[1];
10244                 c[2] *= rsurface.colormod[2];
10245                 c[3] *= rsurface.colormod[3];
10246         }
10247         if (r_refdef.fogenabled)
10248         {
10249                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10250                 {
10251                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10252                         f2 = 1 - f1;
10253                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10254                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10255                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10256                 }
10257         }
10258 //      R_Mesh_ResetTextureState();
10259         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10260         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10261         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10262 }
10263
10264 void R_DrawNoModel(entity_render_t *ent)
10265 {
10266         vec3_t org;
10267         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10268         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10269                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10270         else
10271                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10272 }
10273
10274 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10275 {
10276         vec3_t right1, right2, diff, normal;
10277
10278         VectorSubtract (org2, org1, normal);
10279
10280         // calculate 'right' vector for start
10281         VectorSubtract (r_refdef.view.origin, org1, diff);
10282         CrossProduct (normal, diff, right1);
10283         VectorNormalize (right1);
10284
10285         // calculate 'right' vector for end
10286         VectorSubtract (r_refdef.view.origin, org2, diff);
10287         CrossProduct (normal, diff, right2);
10288         VectorNormalize (right2);
10289
10290         vert[ 0] = org1[0] + width * right1[0];
10291         vert[ 1] = org1[1] + width * right1[1];
10292         vert[ 2] = org1[2] + width * right1[2];
10293         vert[ 3] = org1[0] - width * right1[0];
10294         vert[ 4] = org1[1] - width * right1[1];
10295         vert[ 5] = org1[2] - width * right1[2];
10296         vert[ 6] = org2[0] - width * right2[0];
10297         vert[ 7] = org2[1] - width * right2[1];
10298         vert[ 8] = org2[2] - width * right2[2];
10299         vert[ 9] = org2[0] + width * right2[0];
10300         vert[10] = org2[1] + width * right2[1];
10301         vert[11] = org2[2] + width * right2[2];
10302 }
10303
10304 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)
10305 {
10306         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10307         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10308         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10309         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10310         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10311         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10312         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10313         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10314         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10315         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10316         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10317         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10318 }
10319
10320 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10321 {
10322         int i;
10323         float *vertex3f;
10324         float v[3];
10325         VectorSet(v, x, y, z);
10326         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10327                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10328                         break;
10329         if (i == mesh->numvertices)
10330         {
10331                 if (mesh->numvertices < mesh->maxvertices)
10332                 {
10333                         VectorCopy(v, vertex3f);
10334                         mesh->numvertices++;
10335                 }
10336                 return mesh->numvertices;
10337         }
10338         else
10339                 return i;
10340 }
10341
10342 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10343 {
10344         int i;
10345         int *e, element[3];
10346         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10347         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10348         e = mesh->element3i + mesh->numtriangles * 3;
10349         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10350         {
10351                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10352                 if (mesh->numtriangles < mesh->maxtriangles)
10353                 {
10354                         *e++ = element[0];
10355                         *e++ = element[1];
10356                         *e++ = element[2];
10357                         mesh->numtriangles++;
10358                 }
10359                 element[1] = element[2];
10360         }
10361 }
10362
10363 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10364 {
10365         int i;
10366         int *e, element[3];
10367         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10368         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10369         e = mesh->element3i + mesh->numtriangles * 3;
10370         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10371         {
10372                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10373                 if (mesh->numtriangles < mesh->maxtriangles)
10374                 {
10375                         *e++ = element[0];
10376                         *e++ = element[1];
10377                         *e++ = element[2];
10378                         mesh->numtriangles++;
10379                 }
10380                 element[1] = element[2];
10381         }
10382 }
10383
10384 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10385 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10386 {
10387         int planenum, planenum2;
10388         int w;
10389         int tempnumpoints;
10390         mplane_t *plane, *plane2;
10391         double maxdist;
10392         double temppoints[2][256*3];
10393         // figure out how large a bounding box we need to properly compute this brush
10394         maxdist = 0;
10395         for (w = 0;w < numplanes;w++)
10396                 maxdist = max(maxdist, fabs(planes[w].dist));
10397         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10398         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10399         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10400         {
10401                 w = 0;
10402                 tempnumpoints = 4;
10403                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10404                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10405                 {
10406                         if (planenum2 == planenum)
10407                                 continue;
10408                         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);
10409                         w = !w;
10410                 }
10411                 if (tempnumpoints < 3)
10412                         continue;
10413                 // generate elements forming a triangle fan for this polygon
10414                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10415         }
10416 }
10417
10418 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)
10419 {
10420         texturelayer_t *layer;
10421         layer = t->currentlayers + t->currentnumlayers++;
10422         layer->type = type;
10423         layer->depthmask = depthmask;
10424         layer->blendfunc1 = blendfunc1;
10425         layer->blendfunc2 = blendfunc2;
10426         layer->texture = texture;
10427         layer->texmatrix = *matrix;
10428         layer->color[0] = r;
10429         layer->color[1] = g;
10430         layer->color[2] = b;
10431         layer->color[3] = a;
10432 }
10433
10434 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10435 {
10436         if(parms[0] == 0 && parms[1] == 0)
10437                 return false;
10438         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10439                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10440                         return false;
10441         return true;
10442 }
10443
10444 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10445 {
10446         double index, f;
10447         index = parms[2] + r_refdef.scene.time * parms[3];
10448         index -= floor(index);
10449         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10450         {
10451         default:
10452         case Q3WAVEFUNC_NONE:
10453         case Q3WAVEFUNC_NOISE:
10454         case Q3WAVEFUNC_COUNT:
10455                 f = 0;
10456                 break;
10457         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10458         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10459         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10460         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10461         case Q3WAVEFUNC_TRIANGLE:
10462                 index *= 4;
10463                 f = index - floor(index);
10464                 if (index < 1)
10465                         f = f;
10466                 else if (index < 2)
10467                         f = 1 - f;
10468                 else if (index < 3)
10469                         f = -f;
10470                 else
10471                         f = -(1 - f);
10472                 break;
10473         }
10474         f = parms[0] + parms[1] * f;
10475         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10476                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10477         return (float) f;
10478 }
10479
10480 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10481 {
10482         int w, h, idx;
10483         float f;
10484         float tcmat[12];
10485         matrix4x4_t matrix, temp;
10486         switch(tcmod->tcmod)
10487         {
10488                 case Q3TCMOD_COUNT:
10489                 case Q3TCMOD_NONE:
10490                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10491                                 matrix = r_waterscrollmatrix;
10492                         else
10493                                 matrix = identitymatrix;
10494                         break;
10495                 case Q3TCMOD_ENTITYTRANSLATE:
10496                         // this is used in Q3 to allow the gamecode to control texcoord
10497                         // scrolling on the entity, which is not supported in darkplaces yet.
10498                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10499                         break;
10500                 case Q3TCMOD_ROTATE:
10501                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10502                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10503                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10504                         break;
10505                 case Q3TCMOD_SCALE:
10506                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10507                         break;
10508                 case Q3TCMOD_SCROLL:
10509                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10510                         break;
10511                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10512                         w = (int) tcmod->parms[0];
10513                         h = (int) tcmod->parms[1];
10514                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10515                         f = f - floor(f);
10516                         idx = (int) floor(f * w * h);
10517                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10518                         break;
10519                 case Q3TCMOD_STRETCH:
10520                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10521                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10522                         break;
10523                 case Q3TCMOD_TRANSFORM:
10524                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10525                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10526                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10527                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10528                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10529                         break;
10530                 case Q3TCMOD_TURBULENT:
10531                         // this is handled in the RSurf_PrepareVertices function
10532                         matrix = identitymatrix;
10533                         break;
10534         }
10535         temp = *texmatrix;
10536         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10537 }
10538
10539 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10540 {
10541         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10542         char name[MAX_QPATH];
10543         skinframe_t *skinframe;
10544         unsigned char pixels[296*194];
10545         strlcpy(cache->name, skinname, sizeof(cache->name));
10546         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10547         if (developer_loading.integer)
10548                 Con_Printf("loading %s\n", name);
10549         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10550         if (!skinframe || !skinframe->base)
10551         {
10552                 unsigned char *f;
10553                 fs_offset_t filesize;
10554                 skinframe = NULL;
10555                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10556                 if (f)
10557                 {
10558                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10559                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10560                         Mem_Free(f);
10561                 }
10562         }
10563         cache->skinframe = skinframe;
10564 }
10565
10566 texture_t *R_GetCurrentTexture(texture_t *t)
10567 {
10568         int i;
10569         const entity_render_t *ent = rsurface.entity;
10570         dp_model_t *model = ent->model;
10571         q3shaderinfo_layer_tcmod_t *tcmod;
10572
10573         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10574                 return t->currentframe;
10575         t->update_lastrenderframe = r_textureframe;
10576         t->update_lastrenderentity = (void *)ent;
10577
10578         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10579                 t->camera_entity = ent->entitynumber;
10580         else
10581                 t->camera_entity = 0;
10582
10583         // switch to an alternate material if this is a q1bsp animated material
10584         {
10585                 texture_t *texture = t;
10586                 int s = rsurface.ent_skinnum;
10587                 if ((unsigned int)s >= (unsigned int)model->numskins)
10588                         s = 0;
10589                 if (model->skinscenes)
10590                 {
10591                         if (model->skinscenes[s].framecount > 1)
10592                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10593                         else
10594                                 s = model->skinscenes[s].firstframe;
10595                 }
10596                 if (s > 0)
10597                         t = t + s * model->num_surfaces;
10598                 if (t->animated)
10599                 {
10600                         // use an alternate animation if the entity's frame is not 0,
10601                         // and only if the texture has an alternate animation
10602                         if (rsurface.ent_alttextures && t->anim_total[1])
10603                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10604                         else
10605                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10606                 }
10607                 texture->currentframe = t;
10608         }
10609
10610         // update currentskinframe to be a qw skin or animation frame
10611         if (rsurface.ent_qwskin >= 0)
10612         {
10613                 i = rsurface.ent_qwskin;
10614                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10615                 {
10616                         r_qwskincache_size = cl.maxclients;
10617                         if (r_qwskincache)
10618                                 Mem_Free(r_qwskincache);
10619                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10620                 }
10621                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10622                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10623                 t->currentskinframe = r_qwskincache[i].skinframe;
10624                 if (t->currentskinframe == NULL)
10625                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10626         }
10627         else if (t->numskinframes >= 2)
10628                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10629         if (t->backgroundnumskinframes >= 2)
10630                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10631
10632         t->currentmaterialflags = t->basematerialflags;
10633         t->currentalpha = rsurface.colormod[3];
10634         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10635                 t->currentalpha *= r_wateralpha.value;
10636         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10637                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10638         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10639                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10640         if (!(rsurface.ent_flags & RENDER_LIGHT))
10641                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10642         else if (FAKELIGHT_ENABLED)
10643         {
10644                         // no modellight if using fakelight for the map
10645         }
10646         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10647         {
10648                 // pick a model lighting mode
10649                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10650                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10651                 else
10652                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10653         }
10654         if (rsurface.ent_flags & RENDER_ADDITIVE)
10655                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10656         else if (t->currentalpha < 1)
10657                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10658         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10659                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10660         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10661                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10662         if (t->backgroundnumskinframes)
10663                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10664         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10665         {
10666                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10667                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10668         }
10669         else
10670                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10671         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10672                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10673
10674         // there is no tcmod
10675         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10676         {
10677                 t->currenttexmatrix = r_waterscrollmatrix;
10678                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10679         }
10680         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10681         {
10682                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10683                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10684         }
10685
10686         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10687                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10688         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10689                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10690
10691         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10692         if (t->currentskinframe->qpixels)
10693                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10694         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10695         if (!t->basetexture)
10696                 t->basetexture = r_texture_notexture;
10697         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10698         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10699         t->nmaptexture = t->currentskinframe->nmap;
10700         if (!t->nmaptexture)
10701                 t->nmaptexture = r_texture_blanknormalmap;
10702         t->glosstexture = r_texture_black;
10703         t->glowtexture = t->currentskinframe->glow;
10704         t->fogtexture = t->currentskinframe->fog;
10705         t->reflectmasktexture = t->currentskinframe->reflect;
10706         if (t->backgroundnumskinframes)
10707         {
10708                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10709                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10710                 t->backgroundglosstexture = r_texture_black;
10711                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10712                 if (!t->backgroundnmaptexture)
10713                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10714         }
10715         else
10716         {
10717                 t->backgroundbasetexture = r_texture_white;
10718                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10719                 t->backgroundglosstexture = r_texture_black;
10720                 t->backgroundglowtexture = NULL;
10721         }
10722         t->specularpower = r_shadow_glossexponent.value;
10723         // TODO: store reference values for these in the texture?
10724         t->specularscale = 0;
10725         if (r_shadow_gloss.integer > 0)
10726         {
10727                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10728                 {
10729                         if (r_shadow_glossintensity.value > 0)
10730                         {
10731                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10732                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10733                                 t->specularscale = r_shadow_glossintensity.value;
10734                         }
10735                 }
10736                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10737                 {
10738                         t->glosstexture = r_texture_white;
10739                         t->backgroundglosstexture = r_texture_white;
10740                         t->specularscale = r_shadow_gloss2intensity.value;
10741                         t->specularpower = r_shadow_gloss2exponent.value;
10742                 }
10743         }
10744         t->specularscale *= t->specularscalemod;
10745         t->specularpower *= t->specularpowermod;
10746
10747         // lightmaps mode looks bad with dlights using actual texturing, so turn
10748         // off the colormap and glossmap, but leave the normalmap on as it still
10749         // accurately represents the shading involved
10750         if (gl_lightmaps.integer)
10751         {
10752                 t->basetexture = r_texture_grey128;
10753                 t->pantstexture = r_texture_black;
10754                 t->shirttexture = r_texture_black;
10755                 t->nmaptexture = r_texture_blanknormalmap;
10756                 t->glosstexture = r_texture_black;
10757                 t->glowtexture = NULL;
10758                 t->fogtexture = NULL;
10759                 t->reflectmasktexture = NULL;
10760                 t->backgroundbasetexture = NULL;
10761                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10762                 t->backgroundglosstexture = r_texture_black;
10763                 t->backgroundglowtexture = NULL;
10764                 t->specularscale = 0;
10765                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10766         }
10767
10768         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10769         VectorClear(t->dlightcolor);
10770         t->currentnumlayers = 0;
10771         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10772         {
10773                 int blendfunc1, blendfunc2;
10774                 qboolean depthmask;
10775                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10776                 {
10777                         blendfunc1 = GL_SRC_ALPHA;
10778                         blendfunc2 = GL_ONE;
10779                 }
10780                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10781                 {
10782                         blendfunc1 = GL_SRC_ALPHA;
10783                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10784                 }
10785                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10786                 {
10787                         blendfunc1 = t->customblendfunc[0];
10788                         blendfunc2 = t->customblendfunc[1];
10789                 }
10790                 else
10791                 {
10792                         blendfunc1 = GL_ONE;
10793                         blendfunc2 = GL_ZERO;
10794                 }
10795                 // don't colormod evilblend textures
10796                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10797                         VectorSet(t->lightmapcolor, 1, 1, 1);
10798                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10799                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10800                 {
10801                         // fullbright is not affected by r_refdef.lightmapintensity
10802                         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]);
10803                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10804                                 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]);
10805                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10806                                 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]);
10807                 }
10808                 else
10809                 {
10810                         vec3_t ambientcolor;
10811                         float colorscale;
10812                         // set the color tint used for lights affecting this surface
10813                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10814                         colorscale = 2;
10815                         // q3bsp has no lightmap updates, so the lightstylevalue that
10816                         // would normally be baked into the lightmap must be
10817                         // applied to the color
10818                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10819                         if (model->type == mod_brushq3)
10820                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10821                         colorscale *= r_refdef.lightmapintensity;
10822                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10823                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10824                         // basic lit geometry
10825                         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]);
10826                         // add pants/shirt if needed
10827                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10828                                 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]);
10829                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10830                                 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]);
10831                         // now add ambient passes if needed
10832                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10833                         {
10834                                 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]);
10835                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10836                                         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]);
10837                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10838                                         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]);
10839                         }
10840                 }
10841                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10842                         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]);
10843                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10844                 {
10845                         // if this is opaque use alpha blend which will darken the earlier
10846                         // passes cheaply.
10847                         //
10848                         // if this is an alpha blended material, all the earlier passes
10849                         // were darkened by fog already, so we only need to add the fog
10850                         // color ontop through the fog mask texture
10851                         //
10852                         // if this is an additive blended material, all the earlier passes
10853                         // were darkened by fog already, and we should not add fog color
10854                         // (because the background was not darkened, there is no fog color
10855                         // that was lost behind it).
10856                         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]);
10857                 }
10858         }
10859
10860         return t->currentframe;
10861 }
10862
10863 rsurfacestate_t rsurface;
10864
10865 void R_Mesh_ResizeArrays(int newvertices)
10866 {
10867         unsigned char *base;
10868         size_t size;
10869         if (rsurface.array_size >= newvertices)
10870                 return;
10871         if (rsurface.array_base)
10872                 Mem_Free(rsurface.array_base);
10873         rsurface.array_size = (newvertices + 1023) & ~1023;
10874         size = 0;
10875         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10876         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10877         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10878         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10879         size += rsurface.array_size * sizeof(float[3]);
10880         size += rsurface.array_size * sizeof(float[3]);
10881         size += rsurface.array_size * sizeof(float[3]);
10882         size += rsurface.array_size * sizeof(float[3]);
10883         size += rsurface.array_size * sizeof(float[3]);
10884         size += rsurface.array_size * sizeof(float[3]);
10885         size += rsurface.array_size * sizeof(float[3]);
10886         size += rsurface.array_size * sizeof(float[3]);
10887         size += rsurface.array_size * sizeof(float[4]);
10888         size += rsurface.array_size * sizeof(float[2]);
10889         size += rsurface.array_size * sizeof(float[2]);
10890         size += rsurface.array_size * sizeof(float[4]);
10891         size += rsurface.array_size * sizeof(int[3]);
10892         size += rsurface.array_size * sizeof(unsigned short[3]);
10893         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10894         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10895         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10896         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10897         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10898         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10899         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10900         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10901         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10902         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10903         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10904         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10905         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10906         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10907         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10908         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10909         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10910         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10911         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10912 }
10913
10914 void RSurf_ActiveWorldEntity(void)
10915 {
10916         int newvertices;
10917         dp_model_t *model = r_refdef.scene.worldmodel;
10918         //if (rsurface.entity == r_refdef.scene.worldentity)
10919         //      return;
10920         rsurface.entity = r_refdef.scene.worldentity;
10921         rsurface.skeleton = NULL;
10922         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10923         rsurface.ent_skinnum = 0;
10924         rsurface.ent_qwskin = -1;
10925         rsurface.ent_shadertime = 0;
10926         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10927         newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles);
10928         if (rsurface.array_size < newvertices)
10929                 R_Mesh_ResizeArrays(newvertices);
10930         rsurface.matrix = identitymatrix;
10931         rsurface.inversematrix = identitymatrix;
10932         rsurface.matrixscale = 1;
10933         rsurface.inversematrixscale = 1;
10934         R_EntityMatrix(&identitymatrix);
10935         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10936         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10937         rsurface.fograngerecip = r_refdef.fograngerecip;
10938         rsurface.fogheightfade = r_refdef.fogheightfade;
10939         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10940         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10941         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10942         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10943         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10944         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10945         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10946         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10947         rsurface.colormod[3] = 1;
10948         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);
10949         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10950         rsurface.frameblend[0].lerp = 1;
10951         rsurface.ent_alttextures = false;
10952         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10953         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10954         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10955         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10956         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10957         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10958         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10959         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10960         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10961         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10962         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10963         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10964         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10965         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10966         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10967         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10968         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10969         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10970         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10971         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10972         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10973         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10974         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10975         rsurface.modelelement3i = model->surfmesh.data_element3i;
10976         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10977         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10978         rsurface.modelelement3s = model->surfmesh.data_element3s;
10979         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10980         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10981         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10982         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10983         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10984         rsurface.modelsurfaces = model->data_surfaces;
10985         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10986         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10987         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10988         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10989         rsurface.modelgeneratedvertex = false;
10990         rsurface.batchgeneratedvertex = false;
10991         rsurface.batchfirstvertex = 0;
10992         rsurface.batchnumvertices = 0;
10993         rsurface.batchfirsttriangle = 0;
10994         rsurface.batchnumtriangles = 0;
10995         rsurface.batchvertex3f  = NULL;
10996         rsurface.batchvertex3f_vertexbuffer = NULL;
10997         rsurface.batchvertex3f_bufferoffset = 0;
10998         rsurface.batchsvector3f = NULL;
10999         rsurface.batchsvector3f_vertexbuffer = NULL;
11000         rsurface.batchsvector3f_bufferoffset = 0;
11001         rsurface.batchtvector3f = NULL;
11002         rsurface.batchtvector3f_vertexbuffer = NULL;
11003         rsurface.batchtvector3f_bufferoffset = 0;
11004         rsurface.batchnormal3f  = NULL;
11005         rsurface.batchnormal3f_vertexbuffer = NULL;
11006         rsurface.batchnormal3f_bufferoffset = 0;
11007         rsurface.batchlightmapcolor4f = NULL;
11008         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11009         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11010         rsurface.batchtexcoordtexture2f = NULL;
11011         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11012         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11013         rsurface.batchtexcoordlightmap2f = NULL;
11014         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11015         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11016         rsurface.batchvertexmesh = NULL;
11017         rsurface.batchvertexmeshbuffer = NULL;
11018         rsurface.batchvertexposition = NULL;
11019         rsurface.batchvertexpositionbuffer = NULL;
11020         rsurface.batchelement3i = NULL;
11021         rsurface.batchelement3i_indexbuffer = NULL;
11022         rsurface.batchelement3i_bufferoffset = 0;
11023         rsurface.batchelement3s = NULL;
11024         rsurface.batchelement3s_indexbuffer = NULL;
11025         rsurface.batchelement3s_bufferoffset = 0;
11026         rsurface.passcolor4f = NULL;
11027         rsurface.passcolor4f_vertexbuffer = NULL;
11028         rsurface.passcolor4f_bufferoffset = 0;
11029 }
11030
11031 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11032 {
11033         int newvertices;
11034         dp_model_t *model = ent->model;
11035         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11036         //      return;
11037         rsurface.entity = (entity_render_t *)ent;
11038         rsurface.skeleton = ent->skeleton;
11039         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11040         rsurface.ent_skinnum = ent->skinnum;
11041         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;
11042         rsurface.ent_shadertime = ent->shadertime;
11043         rsurface.ent_flags = ent->flags;
11044         newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles);
11045         if (rsurface.array_size < newvertices)
11046                 R_Mesh_ResizeArrays(newvertices);
11047         rsurface.matrix = ent->matrix;
11048         rsurface.inversematrix = ent->inversematrix;
11049         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11050         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11051         R_EntityMatrix(&rsurface.matrix);
11052         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11053         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11054         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11055         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11056         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11057         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11058         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11059         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11060         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11061         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11062         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11063         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11064         rsurface.colormod[3] = ent->alpha;
11065         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11066         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11067         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11068         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11069         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11070         if (ent->model->brush.submodel && !prepass)
11071         {
11072                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11073                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11074         }
11075         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11076         {
11077                 if (ent->animcache_vertex3f && !r_framedata_failed)
11078                 {
11079                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11080                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11081                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11082                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11083                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11084                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11085                         rsurface.modelvertexposition = ent->animcache_vertexposition;
11086                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
11087                 }
11088                 else if (wanttangents)
11089                 {
11090                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11091                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11092                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11093                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11094                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11095                         rsurface.modelvertexmesh = NULL;
11096                         rsurface.modelvertexmeshbuffer = NULL;
11097                         rsurface.modelvertexposition = NULL;
11098                         rsurface.modelvertexpositionbuffer = NULL;
11099                 }
11100                 else if (wantnormals)
11101                 {
11102                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11103                         rsurface.modelsvector3f = NULL;
11104                         rsurface.modeltvector3f = NULL;
11105                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11106                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11107                         rsurface.modelvertexmesh = NULL;
11108                         rsurface.modelvertexmeshbuffer = NULL;
11109                         rsurface.modelvertexposition = NULL;
11110                         rsurface.modelvertexpositionbuffer = NULL;
11111                 }
11112                 else
11113                 {
11114                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11115                         rsurface.modelsvector3f = NULL;
11116                         rsurface.modeltvector3f = NULL;
11117                         rsurface.modelnormal3f = NULL;
11118                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11119                         rsurface.modelvertexmesh = NULL;
11120                         rsurface.modelvertexmeshbuffer = NULL;
11121                         rsurface.modelvertexposition = NULL;
11122                         rsurface.modelvertexpositionbuffer = NULL;
11123                 }
11124                 rsurface.modelvertex3f_vertexbuffer = 0;
11125                 rsurface.modelvertex3f_bufferoffset = 0;
11126                 rsurface.modelsvector3f_vertexbuffer = 0;
11127                 rsurface.modelsvector3f_bufferoffset = 0;
11128                 rsurface.modeltvector3f_vertexbuffer = 0;
11129                 rsurface.modeltvector3f_bufferoffset = 0;
11130                 rsurface.modelnormal3f_vertexbuffer = 0;
11131                 rsurface.modelnormal3f_bufferoffset = 0;
11132                 rsurface.modelgeneratedvertex = true;
11133         }
11134         else
11135         {
11136                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11137                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11138                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11139                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11140                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11141                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11142                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11143                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11144                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11145                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11146                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11147                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11148                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11149                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11150                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11151                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11152                 rsurface.modelgeneratedvertex = false;
11153         }
11154         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11155         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11156         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11157         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11158         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11159         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11160         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11161         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11162         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11163         rsurface.modelelement3i = model->surfmesh.data_element3i;
11164         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11165         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11166         rsurface.modelelement3s = model->surfmesh.data_element3s;
11167         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11168         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11169         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11170         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11171         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11172         rsurface.modelsurfaces = model->data_surfaces;
11173         rsurface.batchgeneratedvertex = false;
11174         rsurface.batchfirstvertex = 0;
11175         rsurface.batchnumvertices = 0;
11176         rsurface.batchfirsttriangle = 0;
11177         rsurface.batchnumtriangles = 0;
11178         rsurface.batchvertex3f  = NULL;
11179         rsurface.batchvertex3f_vertexbuffer = NULL;
11180         rsurface.batchvertex3f_bufferoffset = 0;
11181         rsurface.batchsvector3f = NULL;
11182         rsurface.batchsvector3f_vertexbuffer = NULL;
11183         rsurface.batchsvector3f_bufferoffset = 0;
11184         rsurface.batchtvector3f = NULL;
11185         rsurface.batchtvector3f_vertexbuffer = NULL;
11186         rsurface.batchtvector3f_bufferoffset = 0;
11187         rsurface.batchnormal3f  = NULL;
11188         rsurface.batchnormal3f_vertexbuffer = NULL;
11189         rsurface.batchnormal3f_bufferoffset = 0;
11190         rsurface.batchlightmapcolor4f = NULL;
11191         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11192         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11193         rsurface.batchtexcoordtexture2f = NULL;
11194         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11195         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11196         rsurface.batchtexcoordlightmap2f = NULL;
11197         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11198         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11199         rsurface.batchvertexmesh = NULL;
11200         rsurface.batchvertexmeshbuffer = NULL;
11201         rsurface.batchvertexposition = NULL;
11202         rsurface.batchvertexpositionbuffer = NULL;
11203         rsurface.batchelement3i = NULL;
11204         rsurface.batchelement3i_indexbuffer = NULL;
11205         rsurface.batchelement3i_bufferoffset = 0;
11206         rsurface.batchelement3s = NULL;
11207         rsurface.batchelement3s_indexbuffer = NULL;
11208         rsurface.batchelement3s_bufferoffset = 0;
11209         rsurface.passcolor4f = NULL;
11210         rsurface.passcolor4f_vertexbuffer = NULL;
11211         rsurface.passcolor4f_bufferoffset = 0;
11212 }
11213
11214 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)
11215 {
11216         int newvertices;
11217
11218         rsurface.entity = r_refdef.scene.worldentity;
11219         rsurface.skeleton = NULL;
11220         rsurface.ent_skinnum = 0;
11221         rsurface.ent_qwskin = -1;
11222         rsurface.ent_shadertime = shadertime;
11223         rsurface.ent_flags = entflags;
11224         rsurface.modelnumvertices = numvertices;
11225         rsurface.modelnumtriangles = numtriangles;
11226         newvertices = max(rsurface.modelnumvertices, rsurface.modelnumtriangles);
11227         if (rsurface.array_size < newvertices)
11228                 R_Mesh_ResizeArrays(newvertices);
11229         rsurface.matrix = *matrix;
11230         rsurface.inversematrix = *inversematrix;
11231         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11232         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11233         R_EntityMatrix(&rsurface.matrix);
11234         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11235         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11236         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11237         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11238         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11239         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11240         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11241         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11242         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11243         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11244         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11245         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11246         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);
11247         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11248         rsurface.frameblend[0].lerp = 1;
11249         rsurface.ent_alttextures = false;
11250         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11251         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11252         if (wanttangents)
11253         {
11254                 rsurface.modelvertex3f = vertex3f;
11255                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11256                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11257                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11258         }
11259         else if (wantnormals)
11260         {
11261                 rsurface.modelvertex3f = vertex3f;
11262                 rsurface.modelsvector3f = NULL;
11263                 rsurface.modeltvector3f = NULL;
11264                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11265         }
11266         else
11267         {
11268                 rsurface.modelvertex3f = vertex3f;
11269                 rsurface.modelsvector3f = NULL;
11270                 rsurface.modeltvector3f = NULL;
11271                 rsurface.modelnormal3f = NULL;
11272         }
11273         rsurface.modelvertexmesh = NULL;
11274         rsurface.modelvertexmeshbuffer = NULL;
11275         rsurface.modelvertexposition = NULL;
11276         rsurface.modelvertexpositionbuffer = NULL;
11277         rsurface.modelvertex3f_vertexbuffer = 0;
11278         rsurface.modelvertex3f_bufferoffset = 0;
11279         rsurface.modelsvector3f_vertexbuffer = 0;
11280         rsurface.modelsvector3f_bufferoffset = 0;
11281         rsurface.modeltvector3f_vertexbuffer = 0;
11282         rsurface.modeltvector3f_bufferoffset = 0;
11283         rsurface.modelnormal3f_vertexbuffer = 0;
11284         rsurface.modelnormal3f_bufferoffset = 0;
11285         rsurface.modelgeneratedvertex = true;
11286         rsurface.modellightmapcolor4f  = color4f;
11287         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11288         rsurface.modellightmapcolor4f_bufferoffset = 0;
11289         rsurface.modeltexcoordtexture2f  = texcoord2f;
11290         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11291         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11292         rsurface.modeltexcoordlightmap2f  = NULL;
11293         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11294         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11295         rsurface.modelelement3i = element3i;
11296         rsurface.modelelement3i_indexbuffer = NULL;
11297         rsurface.modelelement3i_bufferoffset = 0;
11298         rsurface.modelelement3s = element3s;
11299         rsurface.modelelement3s_indexbuffer = NULL;
11300         rsurface.modelelement3s_bufferoffset = 0;
11301         rsurface.modellightmapoffsets = NULL;
11302         rsurface.modelsurfaces = NULL;
11303         rsurface.batchgeneratedvertex = false;
11304         rsurface.batchfirstvertex = 0;
11305         rsurface.batchnumvertices = 0;
11306         rsurface.batchfirsttriangle = 0;
11307         rsurface.batchnumtriangles = 0;
11308         rsurface.batchvertex3f  = NULL;
11309         rsurface.batchvertex3f_vertexbuffer = NULL;
11310         rsurface.batchvertex3f_bufferoffset = 0;
11311         rsurface.batchsvector3f = NULL;
11312         rsurface.batchsvector3f_vertexbuffer = NULL;
11313         rsurface.batchsvector3f_bufferoffset = 0;
11314         rsurface.batchtvector3f = NULL;
11315         rsurface.batchtvector3f_vertexbuffer = NULL;
11316         rsurface.batchtvector3f_bufferoffset = 0;
11317         rsurface.batchnormal3f  = NULL;
11318         rsurface.batchnormal3f_vertexbuffer = NULL;
11319         rsurface.batchnormal3f_bufferoffset = 0;
11320         rsurface.batchlightmapcolor4f = NULL;
11321         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11322         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11323         rsurface.batchtexcoordtexture2f = NULL;
11324         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11325         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11326         rsurface.batchtexcoordlightmap2f = NULL;
11327         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11328         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11329         rsurface.batchvertexmesh = NULL;
11330         rsurface.batchvertexmeshbuffer = NULL;
11331         rsurface.batchvertexposition = NULL;
11332         rsurface.batchvertexpositionbuffer = NULL;
11333         rsurface.batchelement3i = NULL;
11334         rsurface.batchelement3i_indexbuffer = NULL;
11335         rsurface.batchelement3i_bufferoffset = 0;
11336         rsurface.batchelement3s = NULL;
11337         rsurface.batchelement3s_indexbuffer = NULL;
11338         rsurface.batchelement3s_bufferoffset = 0;
11339         rsurface.passcolor4f = NULL;
11340         rsurface.passcolor4f_vertexbuffer = NULL;
11341         rsurface.passcolor4f_bufferoffset = 0;
11342
11343         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11344         {
11345                 if ((wantnormals || wanttangents) && !normal3f)
11346                 {
11347                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11348                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11349                 }
11350                 if (wanttangents && !svector3f)
11351                 {
11352                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11353                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11354                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11355                 }
11356         }
11357 }
11358
11359 float RSurf_FogPoint(const float *v)
11360 {
11361         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11362         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11363         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11364         float FogHeightFade = r_refdef.fogheightfade;
11365         float fogfrac;
11366         unsigned int fogmasktableindex;
11367         if (r_refdef.fogplaneviewabove)
11368                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11369         else
11370                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11371         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11372         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11373 }
11374
11375 float RSurf_FogVertex(const float *v)
11376 {
11377         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11378         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11379         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11380         float FogHeightFade = rsurface.fogheightfade;
11381         float fogfrac;
11382         unsigned int fogmasktableindex;
11383         if (r_refdef.fogplaneviewabove)
11384                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11385         else
11386                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11387         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11388         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11389 }
11390
11391 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11392 {
11393         int i;
11394         for (i = 0;i < numelements;i++)
11395                 outelement3i[i] = inelement3i[i] + adjust;
11396 }
11397
11398 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11399 extern cvar_t gl_vbo;
11400 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11401 {
11402         int deformindex;
11403         int firsttriangle;
11404         int numtriangles;
11405         int firstvertex;
11406         int endvertex;
11407         int numvertices;
11408         int surfacefirsttriangle;
11409         int surfacenumtriangles;
11410         int surfacefirstvertex;
11411         int surfaceendvertex;
11412         int surfacenumvertices;
11413         int needsupdate;
11414         int i, j;
11415         qboolean gaps;
11416         qboolean dynamicvertex;
11417         float amplitude;
11418         float animpos;
11419         float scale;
11420         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11421         float waveparms[4];
11422         q3shaderinfo_deform_t *deform;
11423         const msurface_t *surface, *firstsurface;
11424         r_vertexposition_t *vertexposition;
11425         r_vertexmesh_t *vertexmesh;
11426         if (!texturenumsurfaces)
11427                 return;
11428         // find vertex range of this surface batch
11429         gaps = false;
11430         firstsurface = texturesurfacelist[0];
11431         firsttriangle = firstsurface->num_firsttriangle;
11432         numtriangles = 0;
11433         firstvertex = endvertex = firstsurface->num_firstvertex;
11434         for (i = 0;i < texturenumsurfaces;i++)
11435         {
11436                 surface = texturesurfacelist[i];
11437                 if (surface != firstsurface + i)
11438                         gaps = true;
11439                 surfacefirstvertex = surface->num_firstvertex;
11440                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11441                 surfacenumtriangles = surface->num_triangles;
11442                 if (firstvertex > surfacefirstvertex)
11443                         firstvertex = surfacefirstvertex;
11444                 if (endvertex < surfaceendvertex)
11445                         endvertex = surfaceendvertex;
11446                 numtriangles += surfacenumtriangles;
11447         }
11448
11449         // we now know the vertex range used, and if there are any gaps in it
11450         rsurface.batchfirstvertex = firstvertex;
11451         rsurface.batchnumvertices = endvertex - firstvertex;
11452         rsurface.batchfirsttriangle = firsttriangle;
11453         rsurface.batchnumtriangles = numtriangles;
11454
11455         // this variable holds flags for which properties have been updated that
11456         // may require regenerating vertexmesh or vertexposition arrays...
11457         needsupdate = 0;
11458
11459         // check if any dynamic vertex processing must occur
11460         dynamicvertex = false;
11461
11462         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11463                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11464         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11465         {
11466                 switch (deform->deform)
11467                 {
11468                 default:
11469                 case Q3DEFORM_PROJECTIONSHADOW:
11470                 case Q3DEFORM_TEXT0:
11471                 case Q3DEFORM_TEXT1:
11472                 case Q3DEFORM_TEXT2:
11473                 case Q3DEFORM_TEXT3:
11474                 case Q3DEFORM_TEXT4:
11475                 case Q3DEFORM_TEXT5:
11476                 case Q3DEFORM_TEXT6:
11477                 case Q3DEFORM_TEXT7:
11478                 case Q3DEFORM_NONE:
11479                         break;
11480                 case Q3DEFORM_AUTOSPRITE:
11481                         dynamicvertex = true;
11482                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11483                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11484                         break;
11485                 case Q3DEFORM_AUTOSPRITE2:
11486                         dynamicvertex = true;
11487                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11488                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11489                         break;
11490                 case Q3DEFORM_NORMAL:
11491                         dynamicvertex = true;
11492                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11493                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11494                         break;
11495                 case Q3DEFORM_WAVE:
11496                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11497                                 break; // if wavefunc is a nop, ignore this transform
11498                         dynamicvertex = true;
11499                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11500                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11501                         break;
11502                 case Q3DEFORM_BULGE:
11503                         dynamicvertex = true;
11504                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11505                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11506                         break;
11507                 case Q3DEFORM_MOVE:
11508                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11509                                 break; // if wavefunc is a nop, ignore this transform
11510                         dynamicvertex = true;
11511                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11512                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11513                         break;
11514                 }
11515         }
11516         switch(rsurface.texture->tcgen.tcgen)
11517         {
11518         default:
11519         case Q3TCGEN_TEXTURE:
11520                 break;
11521         case Q3TCGEN_LIGHTMAP:
11522                 dynamicvertex = true;
11523                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11524                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11525                 break;
11526         case Q3TCGEN_VECTOR:
11527                 dynamicvertex = true;
11528                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11529                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11530                 break;
11531         case Q3TCGEN_ENVIRONMENT:
11532                 dynamicvertex = true;
11533                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11534                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11535                 break;
11536         }
11537         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11538         {
11539                 dynamicvertex = true;
11540                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11541                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11542         }
11543
11544         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11545         {
11546                 dynamicvertex = true;
11547                 batchneed |= BATCHNEED_NOGAPS;
11548                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11549         }
11550
11551         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11552         {
11553                 dynamicvertex = true;
11554                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11555                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11556         }
11557
11558         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11559         {
11560                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11561                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11562                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11563                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11564                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11565                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11566                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11567         }
11568
11569         // when the model data has no vertex buffer (dynamic mesh), we need to
11570         // eliminate gaps
11571         if (!rsurface.modelvertexmeshbuffer)
11572                 batchneed |= BATCHNEED_NOGAPS;
11573
11574         // if needsupdate, we have to do a dynamic vertex batch for sure
11575         if (needsupdate & batchneed)
11576                 dynamicvertex = true;
11577
11578         // see if we need to build vertexmesh from arrays
11579         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11580                 dynamicvertex = true;
11581
11582         // see if we need to build vertexposition from arrays
11583         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11584                 dynamicvertex = true;
11585
11586         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11587         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11588                 dynamicvertex = true;
11589
11590         // if there is a chance of animated vertex colors, it's a dynamic batch
11591         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11592                 dynamicvertex = true;
11593
11594         rsurface.batchvertex3f = rsurface.modelvertex3f;
11595         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11596         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11597         rsurface.batchsvector3f = rsurface.modelsvector3f;
11598         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11599         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11600         rsurface.batchtvector3f = rsurface.modeltvector3f;
11601         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11602         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11603         rsurface.batchnormal3f = rsurface.modelnormal3f;
11604         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11605         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11606         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11607         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11608         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11609         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11610         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11611         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11612         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11613         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11614         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11615         rsurface.batchvertexposition = rsurface.modelvertexposition;
11616         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11617         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11618         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11619         rsurface.batchelement3i = rsurface.modelelement3i;
11620         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11621         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11622         rsurface.batchelement3s = rsurface.modelelement3s;
11623         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11624         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11625
11626         // if any dynamic vertex processing has to occur in software, we copy the
11627         // entire surface list together before processing to rebase the vertices
11628         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11629         //
11630         // if any gaps exist and we do not have a static vertex buffer, we have to
11631         // copy the surface list together to avoid wasting upload bandwidth on the
11632         // vertices in the gaps.
11633         //
11634         // if gaps exist and we have a static vertex buffer, we still have to
11635         // combine the index buffer ranges into one dynamic index buffer.
11636         //
11637         // in all cases we end up with data that can be drawn in one call.
11638
11639         if (!dynamicvertex)
11640         {
11641                 // static vertex data, just set pointers...
11642                 rsurface.batchgeneratedvertex = false;
11643                 // if there are gaps, we want to build a combined index buffer,
11644                 // otherwise use the original static buffer with an appropriate offset
11645                 if (gaps)
11646                 {
11647                         firsttriangle = 0;
11648                         numtriangles = 0;
11649                         for (i = 0;i < texturenumsurfaces;i++)
11650                         {
11651                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11652                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11653                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11654                                 numtriangles += surfacenumtriangles;
11655                         }
11656                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11657                         rsurface.batchelement3i_indexbuffer = NULL;
11658                         rsurface.batchelement3i_bufferoffset = 0;
11659                         rsurface.batchelement3s = NULL;
11660                         rsurface.batchelement3s_indexbuffer = NULL;
11661                         rsurface.batchelement3s_bufferoffset = 0;
11662                         if (endvertex <= 65536)
11663                         {
11664                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11665                                 for (i = 0;i < numtriangles*3;i++)
11666                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11667                         }
11668                         rsurface.batchfirsttriangle = firsttriangle;
11669                         rsurface.batchnumtriangles = numtriangles;
11670                 }
11671                 return;
11672         }
11673
11674         // something needs software processing, do it for real...
11675         // we only directly handle interleaved array data in this case...
11676         rsurface.batchgeneratedvertex = true;
11677
11678         // now copy the vertex data into a combined array and make an index array
11679         // (this is what Quake3 does all the time)
11680         //if (gaps || rsurface.batchfirstvertex)
11681         {
11682                 rsurface.batchvertexposition = NULL;
11683                 rsurface.batchvertexpositionbuffer = NULL;
11684                 rsurface.batchvertexmesh = NULL;
11685                 rsurface.batchvertexmeshbuffer = NULL;
11686                 rsurface.batchvertex3f = NULL;
11687                 rsurface.batchvertex3f_vertexbuffer = NULL;
11688                 rsurface.batchvertex3f_bufferoffset = 0;
11689                 rsurface.batchsvector3f = NULL;
11690                 rsurface.batchsvector3f_vertexbuffer = NULL;
11691                 rsurface.batchsvector3f_bufferoffset = 0;
11692                 rsurface.batchtvector3f = NULL;
11693                 rsurface.batchtvector3f_vertexbuffer = NULL;
11694                 rsurface.batchtvector3f_bufferoffset = 0;
11695                 rsurface.batchnormal3f = NULL;
11696                 rsurface.batchnormal3f_vertexbuffer = NULL;
11697                 rsurface.batchnormal3f_bufferoffset = 0;
11698                 rsurface.batchlightmapcolor4f = NULL;
11699                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11700                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11701                 rsurface.batchtexcoordtexture2f = NULL;
11702                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11703                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11704                 rsurface.batchtexcoordlightmap2f = NULL;
11705                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11706                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11707                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11708                 rsurface.batchelement3i_indexbuffer = NULL;
11709                 rsurface.batchelement3i_bufferoffset = 0;
11710                 rsurface.batchelement3s = NULL;
11711                 rsurface.batchelement3s_indexbuffer = NULL;
11712                 rsurface.batchelement3s_bufferoffset = 0;
11713                 // we'll only be setting up certain arrays as needed
11714                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11715                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11716                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11717                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11718                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11719                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11720                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11721                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11722                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11723                 {
11724                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11725                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11726                 }
11727                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11728                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11729                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11730                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11731                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11732                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11733                 numvertices = 0;
11734                 numtriangles = 0;
11735                 for (i = 0;i < texturenumsurfaces;i++)
11736                 {
11737                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11738                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11739                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11740                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11741                         // copy only the data requested
11742                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11743                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11744                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11745                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11746                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11747                         {
11748                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11749                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11750                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11751                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11752                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11753                                 {
11754                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11755                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11756                                 }
11757                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11758                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11759                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11760                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11761                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11762                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11763                         }
11764                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11765                         numvertices += surfacenumvertices;
11766                         numtriangles += surfacenumtriangles;
11767                 }
11768
11769                 // generate a 16bit index array as well if possible
11770                 // (in general, dynamic batches fit)
11771                 if (numvertices <= 65536)
11772                 {
11773                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11774                         for (i = 0;i < numtriangles*3;i++)
11775                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11776                 }
11777
11778                 // since we've copied everything, the batch now starts at 0
11779                 rsurface.batchfirstvertex = 0;
11780                 rsurface.batchnumvertices = numvertices;
11781                 rsurface.batchfirsttriangle = 0;
11782                 rsurface.batchnumtriangles = numtriangles;
11783         }
11784
11785         // q1bsp surfaces rendered in vertex color mode have to have colors
11786         // calculated based on lightstyles
11787         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11788         {
11789                 // generate color arrays for the surfaces in this list
11790                 int c[4];
11791                 int scale;
11792                 int size3;
11793                 const int *offsets;
11794                 const unsigned char *lm;
11795                 numvertices = 0;
11796                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11797                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11798                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11799                 for (i = 0;i < texturenumsurfaces;i++)
11800                 {
11801                         surface = texturesurfacelist[i];
11802                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11803                         surfacenumvertices = surface->num_vertices;
11804                         if (surface->lightmapinfo->samples)
11805                         {
11806                                 for (j = 0;j < surfacenumvertices;j++)
11807                                 {
11808                                         lm = surface->lightmapinfo->samples + offsets[j];
11809                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11810                                         VectorScale(lm, scale, c);
11811                                         if (surface->lightmapinfo->styles[1] != 255)
11812                                         {
11813                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11814                                                 lm += size3;
11815                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11816                                                 VectorMA(c, scale, lm, c);
11817                                                 if (surface->lightmapinfo->styles[2] != 255)
11818                                                 {
11819                                                         lm += size3;
11820                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11821                                                         VectorMA(c, scale, lm, c);
11822                                                         if (surface->lightmapinfo->styles[3] != 255)
11823                                                         {
11824                                                                 lm += size3;
11825                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11826                                                                 VectorMA(c, scale, lm, c);
11827                                                         }
11828                                                 }
11829                                         }
11830                                         c[0] >>= 15;
11831                                         c[1] >>= 15;
11832                                         c[2] >>= 15;
11833                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
11834                                         numvertices++;
11835                                 }
11836                         }
11837                         else
11838                         {
11839                                 for (j = 0;j < surfacenumvertices;j++)
11840                                 {
11841                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11842                                         numvertices++;
11843                                 }
11844                         }
11845                 }
11846         }
11847
11848         // if vertices are deformed (sprite flares and things in maps, possibly
11849         // water waves, bulges and other deformations), modify the copied vertices
11850         // in place
11851         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11852         {
11853                 switch (deform->deform)
11854                 {
11855                 default:
11856                 case Q3DEFORM_PROJECTIONSHADOW:
11857                 case Q3DEFORM_TEXT0:
11858                 case Q3DEFORM_TEXT1:
11859                 case Q3DEFORM_TEXT2:
11860                 case Q3DEFORM_TEXT3:
11861                 case Q3DEFORM_TEXT4:
11862                 case Q3DEFORM_TEXT5:
11863                 case Q3DEFORM_TEXT6:
11864                 case Q3DEFORM_TEXT7:
11865                 case Q3DEFORM_NONE:
11866                         break;
11867                 case Q3DEFORM_AUTOSPRITE:
11868                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11869                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11870                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11871                         VectorNormalize(newforward);
11872                         VectorNormalize(newright);
11873                         VectorNormalize(newup);
11874                         // a single autosprite surface can contain multiple sprites...
11875                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11876                         {
11877                                 VectorClear(center);
11878                                 for (i = 0;i < 4;i++)
11879                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11880                                 VectorScale(center, 0.25f, center);
11881                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11882                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11883                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11884                                 for (i = 0;i < 4;i++)
11885                                 {
11886                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11887                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11888                                 }
11889                         }
11890                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11891                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11892                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
11893                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11894                         rsurface.batchvertex3f_vertexbuffer = NULL;
11895                         rsurface.batchvertex3f_bufferoffset = 0;
11896                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11897                         rsurface.batchsvector3f_vertexbuffer = NULL;
11898                         rsurface.batchsvector3f_bufferoffset = 0;
11899                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11900                         rsurface.batchtvector3f_vertexbuffer = NULL;
11901                         rsurface.batchtvector3f_bufferoffset = 0;
11902                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11903                         rsurface.batchnormal3f_vertexbuffer = NULL;
11904                         rsurface.batchnormal3f_bufferoffset = 0;
11905                         break;
11906                 case Q3DEFORM_AUTOSPRITE2:
11907                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11908                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11909                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11910                         VectorNormalize(newforward);
11911                         VectorNormalize(newright);
11912                         VectorNormalize(newup);
11913                         {
11914                                 const float *v1, *v2;
11915                                 vec3_t start, end;
11916                                 float f, l;
11917                                 struct
11918                                 {
11919                                         float length2;
11920                                         const float *v1;
11921                                         const float *v2;
11922                                 }
11923                                 shortest[2];
11924                                 memset(shortest, 0, sizeof(shortest));
11925                                 // a single autosprite surface can contain multiple sprites...
11926                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11927                                 {
11928                                         VectorClear(center);
11929                                         for (i = 0;i < 4;i++)
11930                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11931                                         VectorScale(center, 0.25f, center);
11932                                         // find the two shortest edges, then use them to define the
11933                                         // axis vectors for rotating around the central axis
11934                                         for (i = 0;i < 6;i++)
11935                                         {
11936                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11937                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11938                                                 l = VectorDistance2(v1, v2);
11939                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11940                                                 if (v1[2] != v2[2])
11941                                                         l += (1.0f / 1024.0f);
11942                                                 if (shortest[0].length2 > l || i == 0)
11943                                                 {
11944                                                         shortest[1] = shortest[0];
11945                                                         shortest[0].length2 = l;
11946                                                         shortest[0].v1 = v1;
11947                                                         shortest[0].v2 = v2;
11948                                                 }
11949                                                 else if (shortest[1].length2 > l || i == 1)
11950                                                 {
11951                                                         shortest[1].length2 = l;
11952                                                         shortest[1].v1 = v1;
11953                                                         shortest[1].v2 = v2;
11954                                                 }
11955                                         }
11956                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11957                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11958                                         // this calculates the right vector from the shortest edge
11959                                         // and the up vector from the edge midpoints
11960                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11961                                         VectorNormalize(right);
11962                                         VectorSubtract(end, start, up);
11963                                         VectorNormalize(up);
11964                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11965                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11966                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11967                                         VectorNegate(forward, forward);
11968                                         VectorReflect(forward, 0, up, forward);
11969                                         VectorNormalize(forward);
11970                                         CrossProduct(up, forward, newright);
11971                                         VectorNormalize(newright);
11972                                         // rotate the quad around the up axis vector, this is made
11973                                         // especially easy by the fact we know the quad is flat,
11974                                         // so we only have to subtract the center position and
11975                                         // measure distance along the right vector, and then
11976                                         // multiply that by the newright vector and add back the
11977                                         // center position
11978                                         // we also need to subtract the old position to undo the
11979                                         // displacement from the center, which we do with a
11980                                         // DotProduct, the subtraction/addition of center is also
11981                                         // optimized into DotProducts here
11982                                         l = DotProduct(right, center);
11983                                         for (i = 0;i < 4;i++)
11984                                         {
11985                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11986                                                 f = DotProduct(right, v1) - l;
11987                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11988                                         }
11989                                 }
11990                         }
11991                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11992                         rsurface.batchvertex3f_vertexbuffer = NULL;
11993                         rsurface.batchvertex3f_bufferoffset = 0;
11994                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11995                         {
11996                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11997                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11998                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11999                                 rsurface.batchnormal3f_bufferoffset = 0;
12000                         }
12001                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12002                         {
12003                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12004                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12005                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12006                                 rsurface.batchsvector3f_bufferoffset = 0;
12007                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12008                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12009                                 rsurface.batchtvector3f_bufferoffset = 0;
12010                         }
12011                         break;
12012                 case Q3DEFORM_NORMAL:
12013                         // deform the normals to make reflections wavey
12014                         for (j = 0;j < rsurface.batchnumvertices;j++)
12015                         {
12016                                 float vertex[3];
12017                                 float *normal = rsurface.array_batchnormal3f + 3*j;
12018                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
12019                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
12020                                 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]);
12021                                 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]);
12022                                 VectorNormalize(normal);
12023                         }
12024                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12025                         rsurface.batchnormal3f_vertexbuffer = NULL;
12026                         rsurface.batchnormal3f_bufferoffset = 0;
12027                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12028                         {
12029                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12030                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12031                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12032                                 rsurface.batchsvector3f_bufferoffset = 0;
12033                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12034                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12035                                 rsurface.batchtvector3f_bufferoffset = 0;
12036                         }
12037                         break;
12038                 case Q3DEFORM_WAVE:
12039                         // deform vertex array to make wavey water and flags and such
12040                         waveparms[0] = deform->waveparms[0];
12041                         waveparms[1] = deform->waveparms[1];
12042                         waveparms[2] = deform->waveparms[2];
12043                         waveparms[3] = deform->waveparms[3];
12044                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12045                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12046                         // this is how a divisor of vertex influence on deformation
12047                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12048                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12049                         for (j = 0;j < rsurface.batchnumvertices;j++)
12050                         {
12051                                 // if the wavefunc depends on time, evaluate it per-vertex
12052                                 if (waveparms[3])
12053                                 {
12054                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12055                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12056                                 }
12057                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12058                         }
12059                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12060                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12061                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12062                         rsurface.batchvertex3f_vertexbuffer = NULL;
12063                         rsurface.batchvertex3f_bufferoffset = 0;
12064                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12065                         rsurface.batchnormal3f_vertexbuffer = NULL;
12066                         rsurface.batchnormal3f_bufferoffset = 0;
12067                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12068                         {
12069                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12070                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12071                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12072                                 rsurface.batchsvector3f_bufferoffset = 0;
12073                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12074                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12075                                 rsurface.batchtvector3f_bufferoffset = 0;
12076                         }
12077                         break;
12078                 case Q3DEFORM_BULGE:
12079                         // deform vertex array to make the surface have moving bulges
12080                         for (j = 0;j < rsurface.batchnumvertices;j++)
12081                         {
12082                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12083                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12084                         }
12085                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12086                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12087                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12088                         rsurface.batchvertex3f_vertexbuffer = NULL;
12089                         rsurface.batchvertex3f_bufferoffset = 0;
12090                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12091                         rsurface.batchnormal3f_vertexbuffer = NULL;
12092                         rsurface.batchnormal3f_bufferoffset = 0;
12093                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12094                         {
12095                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
12096                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12097                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12098                                 rsurface.batchsvector3f_bufferoffset = 0;
12099                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12100                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12101                                 rsurface.batchtvector3f_bufferoffset = 0;
12102                         }
12103                         break;
12104                 case Q3DEFORM_MOVE:
12105                         // deform vertex array
12106                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12107                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12108                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12109                         VectorScale(deform->parms, scale, waveparms);
12110                         for (j = 0;j < rsurface.batchnumvertices;j++)
12111                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12112                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12113                         rsurface.batchvertex3f_vertexbuffer = NULL;
12114                         rsurface.batchvertex3f_bufferoffset = 0;
12115                         break;
12116                 }
12117         }
12118
12119         // generate texcoords based on the chosen texcoord source
12120         switch(rsurface.texture->tcgen.tcgen)
12121         {
12122         default:
12123         case Q3TCGEN_TEXTURE:
12124                 break;
12125         case Q3TCGEN_LIGHTMAP:
12126                 if (rsurface.batchtexcoordlightmap2f)
12127                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12128                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12129                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12130                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12131                 break;
12132         case Q3TCGEN_VECTOR:
12133                 for (j = 0;j < rsurface.batchnumvertices;j++)
12134                 {
12135                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12136                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12137                 }
12138                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12139                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12140                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12141                 break;
12142         case Q3TCGEN_ENVIRONMENT:
12143                 // make environment reflections using a spheremap
12144                 for (j = 0;j < rsurface.batchnumvertices;j++)
12145                 {
12146                         // identical to Q3A's method, but executed in worldspace so
12147                         // carried models can be shiny too
12148
12149                         float viewer[3], d, reflected[3], worldreflected[3];
12150
12151                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12152                         // VectorNormalize(viewer);
12153
12154                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12155
12156                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12157                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12158                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12159                         // note: this is proportinal to viewer, so we can normalize later
12160
12161                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12162                         VectorNormalize(worldreflected);
12163
12164                         // note: this sphere map only uses world x and z!
12165                         // so positive and negative y will LOOK THE SAME.
12166                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12167                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12168                 }
12169                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12170                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12171                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12172                 break;
12173         }
12174         // the only tcmod that needs software vertex processing is turbulent, so
12175         // check for it here and apply the changes if needed
12176         // and we only support that as the first one
12177         // (handling a mixture of turbulent and other tcmods would be problematic
12178         //  without punting it entirely to a software path)
12179         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12180         {
12181                 amplitude = rsurface.texture->tcmods[0].parms[1];
12182                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12183                 for (j = 0;j < rsurface.batchnumvertices;j++)
12184                 {
12185                         rsurface.array_batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12186                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12187                 }
12188                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12189                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12190                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12191         }
12192
12193         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12194         {
12195                 // convert the modified arrays to vertex structs
12196                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12197                 rsurface.batchvertexmeshbuffer = NULL;
12198                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12199                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12200                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12201                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12202                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12203                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12204                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12205                 {
12206                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12207                         {
12208                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12209                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12210                         }
12211                 }
12212                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12213                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12214                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12215                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12216                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12217                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12218                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12219                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12220                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12221         }
12222
12223         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12224         {
12225                 // convert the modified arrays to vertex structs
12226                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12227                 rsurface.batchvertexpositionbuffer = NULL;
12228                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12229                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12230                 else
12231                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12232                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12233         }
12234 }
12235
12236 void RSurf_DrawBatch(void)
12237 {
12238         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12239         // through the pipeline, killing it earlier in the pipeline would have
12240         // per-surface overhead rather than per-batch overhead, so it's best to
12241         // reject it here, before it hits glDraw.
12242         if (rsurface.batchnumtriangles == 0)
12243                 return;
12244 #if 0
12245         // batch debugging code
12246         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12247         {
12248                 int i;
12249                 int j;
12250                 int c;
12251                 const int *e;
12252                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12253                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12254                 {
12255                         c = e[i];
12256                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12257                         {
12258                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12259                                 {
12260                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12261                                                 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);
12262                                         break;
12263                                 }
12264                         }
12265                 }
12266         }
12267 #endif
12268         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);
12269 }
12270
12271 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12272 {
12273         // pick the closest matching water plane
12274         int planeindex, vertexindex, bestplaneindex = -1;
12275         float d, bestd;
12276         vec3_t vert;
12277         const float *v;
12278         r_waterstate_waterplane_t *p;
12279         qboolean prepared = false;
12280         bestd = 0;
12281         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12282         {
12283                 if(p->camera_entity != rsurface.texture->camera_entity)
12284                         continue;
12285                 d = 0;
12286                 if(!prepared)
12287                 {
12288                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12289                         prepared = true;
12290                         if(rsurface.batchnumvertices == 0)
12291                                 break;
12292                 }
12293                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12294                 {
12295                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12296                         d += fabs(PlaneDiff(vert, &p->plane));
12297                 }
12298                 if (bestd > d || bestplaneindex < 0)
12299                 {
12300                         bestd = d;
12301                         bestplaneindex = planeindex;
12302                 }
12303         }
12304         return bestplaneindex;
12305         // NOTE: this MAY return a totally unrelated water plane; we can ignore
12306         // this situation though, as it might be better to render single larger
12307         // batches with useless stuff (backface culled for example) than to
12308         // render multiple smaller batches
12309 }
12310
12311 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12312 {
12313         int i;
12314         for (i = 0;i < rsurface.batchnumvertices;i++)
12315                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12316         rsurface.passcolor4f = rsurface.array_passcolor4f;
12317         rsurface.passcolor4f_vertexbuffer = 0;
12318         rsurface.passcolor4f_bufferoffset = 0;
12319 }
12320
12321 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12322 {
12323         int i;
12324         float f;
12325         const float *v;
12326         const float *c;
12327         float *c2;
12328         if (rsurface.passcolor4f)
12329         {
12330                 // generate color arrays
12331                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12332                 {
12333                         f = RSurf_FogVertex(v);
12334                         c2[0] = c[0] * f;
12335                         c2[1] = c[1] * f;
12336                         c2[2] = c[2] * f;
12337                         c2[3] = c[3];
12338                 }
12339         }
12340         else
12341         {
12342                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12343                 {
12344                         f = RSurf_FogVertex(v);
12345                         c2[0] = f;
12346                         c2[1] = f;
12347                         c2[2] = f;
12348                         c2[3] = 1;
12349                 }
12350         }
12351         rsurface.passcolor4f = rsurface.array_passcolor4f;
12352         rsurface.passcolor4f_vertexbuffer = 0;
12353         rsurface.passcolor4f_bufferoffset = 0;
12354 }
12355
12356 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12357 {
12358         int i;
12359         float f;
12360         const float *v;
12361         const float *c;
12362         float *c2;
12363         if (!rsurface.passcolor4f)
12364                 return;
12365         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12366         {
12367                 f = RSurf_FogVertex(v);
12368                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12369                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12370                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12371                 c2[3] = c[3];
12372         }
12373         rsurface.passcolor4f = rsurface.array_passcolor4f;
12374         rsurface.passcolor4f_vertexbuffer = 0;
12375         rsurface.passcolor4f_bufferoffset = 0;
12376 }
12377
12378 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12379 {
12380         int i;
12381         const float *c;
12382         float *c2;
12383         if (!rsurface.passcolor4f)
12384                 return;
12385         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12386         {
12387                 c2[0] = c[0] * r;
12388                 c2[1] = c[1] * g;
12389                 c2[2] = c[2] * b;
12390                 c2[3] = c[3] * a;
12391         }
12392         rsurface.passcolor4f = rsurface.array_passcolor4f;
12393         rsurface.passcolor4f_vertexbuffer = 0;
12394         rsurface.passcolor4f_bufferoffset = 0;
12395 }
12396
12397 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12398 {
12399         int i;
12400         const float *c;
12401         float *c2;
12402         if (!rsurface.passcolor4f)
12403                 return;
12404         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12405         {
12406                 c2[0] = c[0] + r_refdef.scene.ambient;
12407                 c2[1] = c[1] + r_refdef.scene.ambient;
12408                 c2[2] = c[2] + r_refdef.scene.ambient;
12409                 c2[3] = c[3];
12410         }
12411         rsurface.passcolor4f = rsurface.array_passcolor4f;
12412         rsurface.passcolor4f_vertexbuffer = 0;
12413         rsurface.passcolor4f_bufferoffset = 0;
12414 }
12415
12416 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12417 {
12418         // TODO: optimize
12419         rsurface.passcolor4f = NULL;
12420         rsurface.passcolor4f_vertexbuffer = 0;
12421         rsurface.passcolor4f_bufferoffset = 0;
12422         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12423         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12424         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12425         GL_Color(r, g, b, a);
12426         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12427         RSurf_DrawBatch();
12428 }
12429
12430 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12431 {
12432         // TODO: optimize applyfog && applycolor case
12433         // just apply fog if necessary, and tint the fog color array if necessary
12434         rsurface.passcolor4f = NULL;
12435         rsurface.passcolor4f_vertexbuffer = 0;
12436         rsurface.passcolor4f_bufferoffset = 0;
12437         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12438         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12439         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12440         GL_Color(r, g, b, a);
12441         RSurf_DrawBatch();
12442 }
12443
12444 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12445 {
12446         // TODO: optimize
12447         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12448         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12449         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12450         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12451         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12452         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12453         GL_Color(r, g, b, a);
12454         RSurf_DrawBatch();
12455 }
12456
12457 static void RSurf_DrawBatch_GL11_ClampColor(void)
12458 {
12459         int i;
12460         const float *c1;
12461         float *c2;
12462         if (!rsurface.passcolor4f)
12463                 return;
12464         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12465         {
12466                 c2[0] = bound(0.0f, c1[0], 1.0f);
12467                 c2[1] = bound(0.0f, c1[1], 1.0f);
12468                 c2[2] = bound(0.0f, c1[2], 1.0f);
12469                 c2[3] = bound(0.0f, c1[3], 1.0f);
12470         }
12471 }
12472
12473 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12474 {
12475         int i;
12476         float f;
12477         const float *v;
12478         const float *n;
12479         float *c;
12480         //vec3_t eyedir;
12481
12482         // fake shading
12483         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12484         {
12485                 f = -DotProduct(r_refdef.view.forward, n);
12486                 f = max(0, f);
12487                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12488                 f *= r_refdef.lightmapintensity;
12489                 Vector4Set(c, f, f, f, 1);
12490         }
12491
12492         rsurface.passcolor4f = rsurface.array_passcolor4f;
12493         rsurface.passcolor4f_vertexbuffer = 0;
12494         rsurface.passcolor4f_bufferoffset = 0;
12495 }
12496
12497 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12498 {
12499         RSurf_DrawBatch_GL11_ApplyFakeLight();
12500         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12501         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12502         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12503         GL_Color(r, g, b, a);
12504         RSurf_DrawBatch();
12505 }
12506
12507 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12508 {
12509         int i;
12510         float f;
12511         float alpha;
12512         const float *v;
12513         const float *n;
12514         float *c;
12515         vec3_t ambientcolor;
12516         vec3_t diffusecolor;
12517         vec3_t lightdir;
12518         // TODO: optimize
12519         // model lighting
12520         VectorCopy(rsurface.modellight_lightdir, lightdir);
12521         f = 0.5f * r_refdef.lightmapintensity;
12522         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12523         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12524         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12525         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12526         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12527         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12528         alpha = *a;
12529         if (VectorLength2(diffusecolor) > 0)
12530         {
12531                 // q3-style directional shading
12532                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12533                 {
12534                         if ((f = DotProduct(n, lightdir)) > 0)
12535                                 VectorMA(ambientcolor, f, diffusecolor, c);
12536                         else
12537                                 VectorCopy(ambientcolor, c);
12538                         c[3] = alpha;
12539                 }
12540                 *r = 1;
12541                 *g = 1;
12542                 *b = 1;
12543                 *a = 1;
12544                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12545                 rsurface.passcolor4f_vertexbuffer = 0;
12546                 rsurface.passcolor4f_bufferoffset = 0;
12547                 *applycolor = false;
12548         }
12549         else
12550         {
12551                 *r = ambientcolor[0];
12552                 *g = ambientcolor[1];
12553                 *b = ambientcolor[2];
12554                 rsurface.passcolor4f = NULL;
12555                 rsurface.passcolor4f_vertexbuffer = 0;
12556                 rsurface.passcolor4f_bufferoffset = 0;
12557         }
12558 }
12559
12560 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12561 {
12562         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12563         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12564         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12565         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12566         GL_Color(r, g, b, a);
12567         RSurf_DrawBatch();
12568 }
12569
12570 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12571 {
12572         int i;
12573         float f;
12574         const float *v;
12575         float *c;
12576         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12577         {
12578                 f = 1 - RSurf_FogVertex(v);
12579                 c[0] = r;
12580                 c[1] = g;
12581                 c[2] = b;
12582                 c[3] = f * a;
12583         }
12584 }
12585
12586 void RSurf_SetupDepthAndCulling(void)
12587 {
12588         // submodels are biased to avoid z-fighting with world surfaces that they
12589         // may be exactly overlapping (avoids z-fighting artifacts on certain
12590         // doors and things in Quake maps)
12591         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12592         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12593         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12594         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12595 }
12596
12597 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12598 {
12599         // transparent sky would be ridiculous
12600         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12601                 return;
12602         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12603         skyrenderlater = true;
12604         RSurf_SetupDepthAndCulling();
12605         GL_DepthMask(true);
12606         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12607         // skymasking on them, and Quake3 never did sky masking (unlike
12608         // software Quake and software Quake2), so disable the sky masking
12609         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12610         // and skymasking also looks very bad when noclipping outside the
12611         // level, so don't use it then either.
12612         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12613         {
12614                 R_Mesh_ResetTextureState();
12615                 if (skyrendermasked)
12616                 {
12617                         R_SetupShader_DepthOrShadow();
12618                         // depth-only (masking)
12619                         GL_ColorMask(0,0,0,0);
12620                         // just to make sure that braindead drivers don't draw
12621                         // anything despite that colormask...
12622                         GL_BlendFunc(GL_ZERO, GL_ONE);
12623                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12624                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12625                 }
12626                 else
12627                 {
12628                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12629                         // fog sky
12630                         GL_BlendFunc(GL_ONE, GL_ZERO);
12631                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12632                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12633                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12634                 }
12635                 RSurf_DrawBatch();
12636                 if (skyrendermasked)
12637                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12638         }
12639         R_Mesh_ResetTextureState();
12640         GL_Color(1, 1, 1, 1);
12641 }
12642
12643 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12644 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12645 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12646 {
12647         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12648                 return;
12649         if (prepass)
12650         {
12651                 // render screenspace normalmap to texture
12652                 GL_DepthMask(true);
12653                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12654                 RSurf_DrawBatch();
12655                 return;
12656         }
12657
12658         // bind lightmap texture
12659
12660         // water/refraction/reflection/camera surfaces have to be handled specially
12661         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12662         {
12663                 int start, end, startplaneindex;
12664                 for (start = 0;start < texturenumsurfaces;start = end)
12665                 {
12666                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12667                         if(startplaneindex < 0)
12668                         {
12669                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12670                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12671                                 end = start + 1;
12672                                 continue;
12673                         }
12674                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12675                                 ;
12676                         // now that we have a batch using the same planeindex, render it
12677                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12678                         {
12679                                 // render water or distortion background
12680                                 GL_DepthMask(true);
12681                                 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));
12682                                 RSurf_DrawBatch();
12683                                 // blend surface on top
12684                                 GL_DepthMask(false);
12685                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12686                                 RSurf_DrawBatch();
12687                         }
12688                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12689                         {
12690                                 // render surface with reflection texture as input
12691                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12692                                 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));
12693                                 RSurf_DrawBatch();
12694                         }
12695                 }
12696                 return;
12697         }
12698
12699         // render surface batch normally
12700         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12701         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12702         RSurf_DrawBatch();
12703 }
12704
12705 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12706 {
12707         // OpenGL 1.3 path - anything not completely ancient
12708         qboolean applycolor;
12709         qboolean applyfog;
12710         int layerindex;
12711         const texturelayer_t *layer;
12712         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);
12713         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12714
12715         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12716         {
12717                 vec4_t layercolor;
12718                 int layertexrgbscale;
12719                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12720                 {
12721                         if (layerindex == 0)
12722                                 GL_AlphaTest(true);
12723                         else
12724                         {
12725                                 GL_AlphaTest(false);
12726                                 GL_DepthFunc(GL_EQUAL);
12727                         }
12728                 }
12729                 GL_DepthMask(layer->depthmask && writedepth);
12730                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12731                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12732                 {
12733                         layertexrgbscale = 4;
12734                         VectorScale(layer->color, 0.25f, layercolor);
12735                 }
12736                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12737                 {
12738                         layertexrgbscale = 2;
12739                         VectorScale(layer->color, 0.5f, layercolor);
12740                 }
12741                 else
12742                 {
12743                         layertexrgbscale = 1;
12744                         VectorScale(layer->color, 1.0f, layercolor);
12745                 }
12746                 layercolor[3] = layer->color[3];
12747                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12748                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12749                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12750                 switch (layer->type)
12751                 {
12752                 case TEXTURELAYERTYPE_LITTEXTURE:
12753                         // single-pass lightmapped texture with 2x rgbscale
12754                         R_Mesh_TexBind(0, r_texture_white);
12755                         R_Mesh_TexMatrix(0, NULL);
12756                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12757                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12758                         R_Mesh_TexBind(1, layer->texture);
12759                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12760                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12761                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12762                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12763                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12764                         else if (FAKELIGHT_ENABLED)
12765                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12766                         else if (rsurface.uselightmaptexture)
12767                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12768                         else
12769                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12770                         break;
12771                 case TEXTURELAYERTYPE_TEXTURE:
12772                         // singletexture unlit texture with transparency support
12773                         R_Mesh_TexBind(0, layer->texture);
12774                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12775                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12776                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12777                         R_Mesh_TexBind(1, 0);
12778                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12779                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12780                         break;
12781                 case TEXTURELAYERTYPE_FOG:
12782                         // singletexture fogging
12783                         if (layer->texture)
12784                         {
12785                                 R_Mesh_TexBind(0, layer->texture);
12786                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12787                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12788                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12789                         }
12790                         else
12791                         {
12792                                 R_Mesh_TexBind(0, 0);
12793                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12794                         }
12795                         R_Mesh_TexBind(1, 0);
12796                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12797                         // generate a color array for the fog pass
12798                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12799                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12800                         RSurf_DrawBatch();
12801                         break;
12802                 default:
12803                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12804                 }
12805         }
12806         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12807         {
12808                 GL_DepthFunc(GL_LEQUAL);
12809                 GL_AlphaTest(false);
12810         }
12811 }
12812
12813 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12814 {
12815         // OpenGL 1.1 - crusty old voodoo path
12816         qboolean applyfog;
12817         int layerindex;
12818         const texturelayer_t *layer;
12819         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);
12820         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12821
12822         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12823         {
12824                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12825                 {
12826                         if (layerindex == 0)
12827                                 GL_AlphaTest(true);
12828                         else
12829                         {
12830                                 GL_AlphaTest(false);
12831                                 GL_DepthFunc(GL_EQUAL);
12832                         }
12833                 }
12834                 GL_DepthMask(layer->depthmask && writedepth);
12835                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12836                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12837                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12838                 switch (layer->type)
12839                 {
12840                 case TEXTURELAYERTYPE_LITTEXTURE:
12841                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12842                         {
12843                                 // two-pass lit texture with 2x rgbscale
12844                                 // first the lightmap pass
12845                                 R_Mesh_TexBind(0, r_texture_white);
12846                                 R_Mesh_TexMatrix(0, NULL);
12847                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12848                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12849                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12850                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12851                                 else if (FAKELIGHT_ENABLED)
12852                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12853                                 else if (rsurface.uselightmaptexture)
12854                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12855                                 else
12856                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12857                                 // then apply the texture to it
12858                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12859                                 R_Mesh_TexBind(0, layer->texture);
12860                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12861                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12862                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12863                                 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);
12864                         }
12865                         else
12866                         {
12867                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12868                                 R_Mesh_TexBind(0, layer->texture);
12869                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12870                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12871                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12872                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12873                                         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);
12874                                 else
12875                                         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);
12876                         }
12877                         break;
12878                 case TEXTURELAYERTYPE_TEXTURE:
12879                         // singletexture unlit texture with transparency support
12880                         R_Mesh_TexBind(0, layer->texture);
12881                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12882                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12883                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12884                         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);
12885                         break;
12886                 case TEXTURELAYERTYPE_FOG:
12887                         // singletexture fogging
12888                         if (layer->texture)
12889                         {
12890                                 R_Mesh_TexBind(0, layer->texture);
12891                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12892                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12893                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12894                         }
12895                         else
12896                         {
12897                                 R_Mesh_TexBind(0, 0);
12898                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12899                         }
12900                         // generate a color array for the fog pass
12901                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12902                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12903                         RSurf_DrawBatch();
12904                         break;
12905                 default:
12906                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12907                 }
12908         }
12909         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12910         {
12911                 GL_DepthFunc(GL_LEQUAL);
12912                 GL_AlphaTest(false);
12913         }
12914 }
12915
12916 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12917 {
12918         int vi;
12919         int j;
12920         r_vertexgeneric_t *batchvertex;
12921         float c[4];
12922
12923         GL_AlphaTest(false);
12924 //      R_Mesh_ResetTextureState();
12925         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12926
12927         if(rsurface.texture && rsurface.texture->currentskinframe)
12928         {
12929                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12930                 c[3] *= rsurface.texture->currentalpha;
12931         }
12932         else
12933         {
12934                 c[0] = 1;
12935                 c[1] = 0;
12936                 c[2] = 1;
12937                 c[3] = 1;
12938         }
12939
12940         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12941         {
12942                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12943                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12944                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12945         }
12946
12947         // brighten it up (as texture value 127 means "unlit")
12948         c[0] *= 2 * r_refdef.view.colorscale;
12949         c[1] *= 2 * r_refdef.view.colorscale;
12950         c[2] *= 2 * r_refdef.view.colorscale;
12951
12952         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12953                 c[3] *= r_wateralpha.value;
12954
12955         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12956         {
12957                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12958                 GL_DepthMask(false);
12959         }
12960         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12961         {
12962                 GL_BlendFunc(GL_ONE, GL_ONE);
12963                 GL_DepthMask(false);
12964         }
12965         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12966         {
12967                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12968                 GL_DepthMask(false);
12969         }
12970         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12971         {
12972                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12973                 GL_DepthMask(false);
12974         }
12975         else
12976         {
12977                 GL_BlendFunc(GL_ONE, GL_ZERO);
12978                 GL_DepthMask(writedepth);
12979         }
12980
12981         if (r_showsurfaces.integer == 3)
12982         {
12983                 rsurface.passcolor4f = NULL;
12984
12985                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12986                 {
12987                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12988
12989                         rsurface.passcolor4f = NULL;
12990                         rsurface.passcolor4f_vertexbuffer = 0;
12991                         rsurface.passcolor4f_bufferoffset = 0;
12992                 }
12993                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12994                 {
12995                         qboolean applycolor = true;
12996                         float one = 1.0;
12997
12998                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12999
13000                         r_refdef.lightmapintensity = 1;
13001                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
13002                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13003                 }
13004                 else if (FAKELIGHT_ENABLED)
13005                 {
13006                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13007
13008                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
13009                         RSurf_DrawBatch_GL11_ApplyFakeLight();
13010                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13011                 }
13012                 else
13013                 {
13014                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13015
13016                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13017                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13018                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13019                 }
13020
13021                 if(!rsurface.passcolor4f)
13022                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13023
13024                 RSurf_DrawBatch_GL11_ApplyAmbient();
13025                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13026                 if(r_refdef.fogenabled)
13027                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13028                 RSurf_DrawBatch_GL11_ClampColor();
13029
13030                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13031                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13032                 RSurf_DrawBatch();
13033         }
13034         else if (!r_refdef.view.showdebug)
13035         {
13036                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13037                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13038                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13039                 {
13040                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13041                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13042                 }
13043                 R_Mesh_PrepareVertices_Generic_Unlock();
13044                 RSurf_DrawBatch();
13045         }
13046         else if (r_showsurfaces.integer == 4)
13047         {
13048                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13049                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13050                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13051                 {
13052                         unsigned char c = vi << 3;
13053                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13054                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13055                 }
13056                 R_Mesh_PrepareVertices_Generic_Unlock();
13057                 RSurf_DrawBatch();
13058         }
13059         else if (r_showsurfaces.integer == 2)
13060         {
13061                 const int *e;
13062                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13063                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13064                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13065                 {
13066                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13067                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13068                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13069                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13070                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13071                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13072                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13073                 }
13074                 R_Mesh_PrepareVertices_Generic_Unlock();
13075                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13076         }
13077         else
13078         {
13079                 int texturesurfaceindex;
13080                 int k;
13081                 const msurface_t *surface;
13082                 unsigned char surfacecolor4ub[4];
13083                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13084                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13085                 vi = 0;
13086                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13087                 {
13088                         surface = texturesurfacelist[texturesurfaceindex];
13089                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13090                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13091                         for (j = 0;j < surface->num_vertices;j++)
13092                         {
13093                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13094                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13095                                 vi++;
13096                         }
13097                 }
13098                 R_Mesh_PrepareVertices_Generic_Unlock();
13099                 RSurf_DrawBatch();
13100         }
13101 }
13102
13103 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13104 {
13105         CHECKGLERROR
13106         RSurf_SetupDepthAndCulling();
13107         if (r_showsurfaces.integer)
13108         {
13109                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13110                 return;
13111         }
13112         switch (vid.renderpath)
13113         {
13114         case RENDERPATH_GL20:
13115         case RENDERPATH_CGGL:
13116         case RENDERPATH_D3D9:
13117         case RENDERPATH_D3D10:
13118         case RENDERPATH_D3D11:
13119                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13120                 break;
13121         case RENDERPATH_GL13:
13122                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13123                 break;
13124         case RENDERPATH_GL11:
13125                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13126                 break;
13127         }
13128         CHECKGLERROR
13129 }
13130
13131 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13132 {
13133         CHECKGLERROR
13134         RSurf_SetupDepthAndCulling();
13135         if (r_showsurfaces.integer)
13136         {
13137                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13138                 return;
13139         }
13140         switch (vid.renderpath)
13141         {
13142         case RENDERPATH_GL20:
13143         case RENDERPATH_CGGL:
13144         case RENDERPATH_D3D9:
13145         case RENDERPATH_D3D10:
13146         case RENDERPATH_D3D11:
13147                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13148                 break;
13149         case RENDERPATH_GL13:
13150                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13151                 break;
13152         case RENDERPATH_GL11:
13153                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13154                 break;
13155         }
13156         CHECKGLERROR
13157 }
13158
13159 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13160 {
13161         int i, j;
13162         int texturenumsurfaces, endsurface;
13163         texture_t *texture;
13164         const msurface_t *surface;
13165 #define MAXBATCH_TRANSPARENTSURFACES 256
13166         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13167
13168         // if the model is static it doesn't matter what value we give for
13169         // wantnormals and wanttangents, so this logic uses only rules applicable
13170         // to a model, knowing that they are meaningless otherwise
13171         if (ent == r_refdef.scene.worldentity)
13172                 RSurf_ActiveWorldEntity();
13173         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13174                 RSurf_ActiveModelEntity(ent, false, false, false);
13175         else
13176         {
13177                 switch (vid.renderpath)
13178                 {
13179                 case RENDERPATH_GL20:
13180                 case RENDERPATH_CGGL:
13181                 case RENDERPATH_D3D9:
13182                 case RENDERPATH_D3D10:
13183                 case RENDERPATH_D3D11:
13184                         RSurf_ActiveModelEntity(ent, true, true, false);
13185                         break;
13186                 case RENDERPATH_GL13:
13187                 case RENDERPATH_GL11:
13188                         RSurf_ActiveModelEntity(ent, true, false, false);
13189                         break;
13190                 }
13191         }
13192
13193         if (r_transparentdepthmasking.integer)
13194         {
13195                 qboolean setup = false;
13196                 for (i = 0;i < numsurfaces;i = j)
13197                 {
13198                         j = i + 1;
13199                         surface = rsurface.modelsurfaces + surfacelist[i];
13200                         texture = surface->texture;
13201                         rsurface.texture = R_GetCurrentTexture(texture);
13202                         rsurface.lightmaptexture = NULL;
13203                         rsurface.deluxemaptexture = NULL;
13204                         rsurface.uselightmaptexture = false;
13205                         // scan ahead until we find a different texture
13206                         endsurface = min(i + 1024, numsurfaces);
13207                         texturenumsurfaces = 0;
13208                         texturesurfacelist[texturenumsurfaces++] = surface;
13209                         for (;j < endsurface;j++)
13210                         {
13211                                 surface = rsurface.modelsurfaces + surfacelist[j];
13212                                 if (texture != surface->texture)
13213                                         break;
13214                                 texturesurfacelist[texturenumsurfaces++] = surface;
13215                         }
13216                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13217                                 continue;
13218                         // render the range of surfaces as depth
13219                         if (!setup)
13220                         {
13221                                 setup = true;
13222                                 GL_ColorMask(0,0,0,0);
13223                                 GL_Color(1,1,1,1);
13224                                 GL_DepthTest(true);
13225                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13226                                 GL_DepthMask(true);
13227                                 GL_AlphaTest(false);
13228 //                              R_Mesh_ResetTextureState();
13229                                 R_SetupShader_DepthOrShadow();
13230                         }
13231                         RSurf_SetupDepthAndCulling();
13232                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13233                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13234                         RSurf_DrawBatch();
13235                 }
13236                 if (setup)
13237                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13238         }
13239
13240         for (i = 0;i < numsurfaces;i = j)
13241         {
13242                 j = i + 1;
13243                 surface = rsurface.modelsurfaces + surfacelist[i];
13244                 texture = surface->texture;
13245                 rsurface.texture = R_GetCurrentTexture(texture);
13246                 // scan ahead until we find a different texture
13247                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13248                 texturenumsurfaces = 0;
13249                 texturesurfacelist[texturenumsurfaces++] = surface;
13250                 if(FAKELIGHT_ENABLED)
13251                 {
13252                         rsurface.lightmaptexture = NULL;
13253                         rsurface.deluxemaptexture = NULL;
13254                         rsurface.uselightmaptexture = false;
13255                         for (;j < endsurface;j++)
13256                         {
13257                                 surface = rsurface.modelsurfaces + surfacelist[j];
13258                                 if (texture != surface->texture)
13259                                         break;
13260                                 texturesurfacelist[texturenumsurfaces++] = surface;
13261                         }
13262                 }
13263                 else
13264                 {
13265                         rsurface.lightmaptexture = surface->lightmaptexture;
13266                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13267                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13268                         for (;j < endsurface;j++)
13269                         {
13270                                 surface = rsurface.modelsurfaces + surfacelist[j];
13271                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13272                                         break;
13273                                 texturesurfacelist[texturenumsurfaces++] = surface;
13274                         }
13275                 }
13276                 // render the range of surfaces
13277                 if (ent == r_refdef.scene.worldentity)
13278                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13279                 else
13280                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13281         }
13282         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13283         GL_AlphaTest(false);
13284 }
13285
13286 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13287 {
13288         // transparent surfaces get pushed off into the transparent queue
13289         int surfacelistindex;
13290         const msurface_t *surface;
13291         vec3_t tempcenter, center;
13292         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13293         {
13294                 surface = texturesurfacelist[surfacelistindex];
13295                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13296                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13297                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13298                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13299                 if (queueentity->transparent_offset) // transparent offset
13300                 {
13301                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13302                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13303                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13304                 }
13305                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13306         }
13307 }
13308
13309 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13310 {
13311         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13312                 return;
13313         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13314                 return;
13315         RSurf_SetupDepthAndCulling();
13316         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13317         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13318         RSurf_DrawBatch();
13319 }
13320
13321 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13322 {
13323         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13324         CHECKGLERROR
13325         if (depthonly)
13326                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13327         else if (prepass)
13328         {
13329                 if (!rsurface.texture->currentnumlayers)
13330                         return;
13331                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13332                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13333                 else
13334                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13335         }
13336         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13337                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13338         else if (!rsurface.texture->currentnumlayers)
13339                 return;
13340         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13341         {
13342                 // in the deferred case, transparent surfaces were queued during prepass
13343                 if (!r_shadow_usingdeferredprepass)
13344                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13345         }
13346         else
13347         {
13348                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13349                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13350         }
13351         CHECKGLERROR
13352 }
13353
13354 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13355 {
13356         int i, j;
13357         texture_t *texture;
13358         // break the surface list down into batches by texture and use of lightmapping
13359         for (i = 0;i < numsurfaces;i = j)
13360         {
13361                 j = i + 1;
13362                 // texture is the base texture pointer, rsurface.texture is the
13363                 // current frame/skin the texture is directing us to use (for example
13364                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13365                 // use skin 1 instead)
13366                 texture = surfacelist[i]->texture;
13367                 rsurface.texture = R_GetCurrentTexture(texture);
13368                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13369                 {
13370                         // if this texture is not the kind we want, skip ahead to the next one
13371                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13372                                 ;
13373                         continue;
13374                 }
13375                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13376                 {
13377                         rsurface.lightmaptexture = NULL;
13378                         rsurface.deluxemaptexture = NULL;
13379                         rsurface.uselightmaptexture = false;
13380                         // simply scan ahead until we find a different texture or lightmap state
13381                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13382                                 ;
13383                 }
13384                 else
13385                 {
13386                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13387                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13388                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13389                         // simply scan ahead until we find a different texture or lightmap state
13390                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13391                                 ;
13392                 }
13393                 // render the range of surfaces
13394                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13395         }
13396 }
13397
13398 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13399 {
13400         CHECKGLERROR
13401         if (depthonly)
13402                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13403         else if (prepass)
13404         {
13405                 if (!rsurface.texture->currentnumlayers)
13406                         return;
13407                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13408                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13409                 else
13410                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13411         }
13412         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13413                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13414         else if (!rsurface.texture->currentnumlayers)
13415                 return;
13416         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13417         {
13418                 // in the deferred case, transparent surfaces were queued during prepass
13419                 if (!r_shadow_usingdeferredprepass)
13420                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13421         }
13422         else
13423         {
13424                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13425                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13426         }
13427         CHECKGLERROR
13428 }
13429
13430 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13431 {
13432         int i, j;
13433         texture_t *texture;
13434         // break the surface list down into batches by texture and use of lightmapping
13435         for (i = 0;i < numsurfaces;i = j)
13436         {
13437                 j = i + 1;
13438                 // texture is the base texture pointer, rsurface.texture is the
13439                 // current frame/skin the texture is directing us to use (for example
13440                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13441                 // use skin 1 instead)
13442                 texture = surfacelist[i]->texture;
13443                 rsurface.texture = R_GetCurrentTexture(texture);
13444                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13445                 {
13446                         // if this texture is not the kind we want, skip ahead to the next one
13447                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13448                                 ;
13449                         continue;
13450                 }
13451                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13452                 {
13453                         rsurface.lightmaptexture = NULL;
13454                         rsurface.deluxemaptexture = NULL;
13455                         rsurface.uselightmaptexture = false;
13456                         // simply scan ahead until we find a different texture or lightmap state
13457                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13458                                 ;
13459                 }
13460                 else
13461                 {
13462                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13463                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13464                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13465                         // simply scan ahead until we find a different texture or lightmap state
13466                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13467                                 ;
13468                 }
13469                 // render the range of surfaces
13470                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13471         }
13472 }
13473
13474 float locboxvertex3f[6*4*3] =
13475 {
13476         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13477         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13478         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13479         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13480         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13481         1,0,0, 0,0,0, 0,1,0, 1,1,0
13482 };
13483
13484 unsigned short locboxelements[6*2*3] =
13485 {
13486          0, 1, 2, 0, 2, 3,
13487          4, 5, 6, 4, 6, 7,
13488          8, 9,10, 8,10,11,
13489         12,13,14, 12,14,15,
13490         16,17,18, 16,18,19,
13491         20,21,22, 20,22,23
13492 };
13493
13494 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13495 {
13496         int i, j;
13497         cl_locnode_t *loc = (cl_locnode_t *)ent;
13498         vec3_t mins, size;
13499         float vertex3f[6*4*3];
13500         CHECKGLERROR
13501         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13502         GL_DepthMask(false);
13503         GL_DepthRange(0, 1);
13504         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13505         GL_DepthTest(true);
13506         GL_CullFace(GL_NONE);
13507         R_EntityMatrix(&identitymatrix);
13508
13509 //      R_Mesh_ResetTextureState();
13510
13511         i = surfacelist[0];
13512         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13513                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13514                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13515                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13516
13517         if (VectorCompare(loc->mins, loc->maxs))
13518         {
13519                 VectorSet(size, 2, 2, 2);
13520                 VectorMA(loc->mins, -0.5f, size, mins);
13521         }
13522         else
13523         {
13524                 VectorCopy(loc->mins, mins);
13525                 VectorSubtract(loc->maxs, loc->mins, size);
13526         }
13527
13528         for (i = 0;i < 6*4*3;)
13529                 for (j = 0;j < 3;j++, i++)
13530                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13531
13532         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13533         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13534         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13535 }
13536
13537 void R_DrawLocs(void)
13538 {
13539         int index;
13540         cl_locnode_t *loc, *nearestloc;
13541         vec3_t center;
13542         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13543         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13544         {
13545                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13546                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13547         }
13548 }
13549
13550 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13551 {
13552         if (decalsystem->decals)
13553                 Mem_Free(decalsystem->decals);
13554         memset(decalsystem, 0, sizeof(*decalsystem));
13555 }
13556
13557 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)
13558 {
13559         tridecal_t *decal;
13560         tridecal_t *decals;
13561         int i;
13562
13563         // expand or initialize the system
13564         if (decalsystem->maxdecals <= decalsystem->numdecals)
13565         {
13566                 decalsystem_t old = *decalsystem;
13567                 qboolean useshortelements;
13568                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13569                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13570                 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)));
13571                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13572                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13573                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13574                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13575                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13576                 if (decalsystem->numdecals)
13577                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13578                 if (old.decals)
13579                         Mem_Free(old.decals);
13580                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13581                         decalsystem->element3i[i] = i;
13582                 if (useshortelements)
13583                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13584                                 decalsystem->element3s[i] = i;
13585         }
13586
13587         // grab a decal and search for another free slot for the next one
13588         decals = decalsystem->decals;
13589         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13590         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13591                 ;
13592         decalsystem->freedecal = i;
13593         if (decalsystem->numdecals <= i)
13594                 decalsystem->numdecals = i + 1;
13595
13596         // initialize the decal
13597         decal->lived = 0;
13598         decal->triangleindex = triangleindex;
13599         decal->surfaceindex = surfaceindex;
13600         decal->decalsequence = decalsequence;
13601         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13602         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13603         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13604         decal->color4ub[0][3] = 255;
13605         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13606         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13607         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13608         decal->color4ub[1][3] = 255;
13609         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13610         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13611         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13612         decal->color4ub[2][3] = 255;
13613         decal->vertex3f[0][0] = v0[0];
13614         decal->vertex3f[0][1] = v0[1];
13615         decal->vertex3f[0][2] = v0[2];
13616         decal->vertex3f[1][0] = v1[0];
13617         decal->vertex3f[1][1] = v1[1];
13618         decal->vertex3f[1][2] = v1[2];
13619         decal->vertex3f[2][0] = v2[0];
13620         decal->vertex3f[2][1] = v2[1];
13621         decal->vertex3f[2][2] = v2[2];
13622         decal->texcoord2f[0][0] = t0[0];
13623         decal->texcoord2f[0][1] = t0[1];
13624         decal->texcoord2f[1][0] = t1[0];
13625         decal->texcoord2f[1][1] = t1[1];
13626         decal->texcoord2f[2][0] = t2[0];
13627         decal->texcoord2f[2][1] = t2[1];
13628 }
13629
13630 extern cvar_t cl_decals_bias;
13631 extern cvar_t cl_decals_models;
13632 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13633 // baseparms, parms, temps
13634 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)
13635 {
13636         int cornerindex;
13637         int index;
13638         float v[9][3];
13639         const float *vertex3f;
13640         int numpoints;
13641         float points[2][9][3];
13642         float temp[3];
13643         float tc[9][2];
13644         float f;
13645         float c[9][4];
13646         const int *e;
13647
13648         e = rsurface.modelelement3i + 3*triangleindex;
13649
13650         vertex3f = rsurface.modelvertex3f;
13651
13652         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13653         {
13654                 index = 3*e[cornerindex];
13655                 VectorCopy(vertex3f + index, v[cornerindex]);
13656         }
13657         // cull backfaces
13658         //TriangleNormal(v[0], v[1], v[2], normal);
13659         //if (DotProduct(normal, localnormal) < 0.0f)
13660         //      continue;
13661         // clip by each of the box planes formed from the projection matrix
13662         // if anything survives, we emit the decal
13663         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]);
13664         if (numpoints < 3)
13665                 return;
13666         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]);
13667         if (numpoints < 3)
13668                 return;
13669         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]);
13670         if (numpoints < 3)
13671                 return;
13672         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]);
13673         if (numpoints < 3)
13674                 return;
13675         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]);
13676         if (numpoints < 3)
13677                 return;
13678         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]);
13679         if (numpoints < 3)
13680                 return;
13681         // some part of the triangle survived, so we have to accept it...
13682         if (dynamic)
13683         {
13684                 // dynamic always uses the original triangle
13685                 numpoints = 3;
13686                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13687                 {
13688                         index = 3*e[cornerindex];
13689                         VectorCopy(vertex3f + index, v[cornerindex]);
13690                 }
13691         }
13692         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13693         {
13694                 // convert vertex positions to texcoords
13695                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13696                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13697                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13698                 // calculate distance fade from the projection origin
13699                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13700                 f = bound(0.0f, f, 1.0f);
13701                 c[cornerindex][0] = r * f;
13702                 c[cornerindex][1] = g * f;
13703                 c[cornerindex][2] = b * f;
13704                 c[cornerindex][3] = 1.0f;
13705                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13706         }
13707         if (dynamic)
13708                 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);
13709         else
13710                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13711                         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);
13712 }
13713 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)
13714 {
13715         matrix4x4_t projection;
13716         decalsystem_t *decalsystem;
13717         qboolean dynamic;
13718         dp_model_t *model;
13719         const msurface_t *surface;
13720         const msurface_t *surfaces;
13721         const int *surfacelist;
13722         const texture_t *texture;
13723         int numtriangles;
13724         int numsurfacelist;
13725         int surfacelistindex;
13726         int surfaceindex;
13727         int triangleindex;
13728         float localorigin[3];
13729         float localnormal[3];
13730         float localmins[3];
13731         float localmaxs[3];
13732         float localsize;
13733         //float normal[3];
13734         float planes[6][4];
13735         float angles[3];
13736         bih_t *bih;
13737         int bih_triangles_count;
13738         int bih_triangles[256];
13739         int bih_surfaces[256];
13740
13741         decalsystem = &ent->decalsystem;
13742         model = ent->model;
13743         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13744         {
13745                 R_DecalSystem_Reset(&ent->decalsystem);
13746                 return;
13747         }
13748
13749         if (!model->brush.data_leafs && !cl_decals_models.integer)
13750         {
13751                 if (decalsystem->model)
13752                         R_DecalSystem_Reset(decalsystem);
13753                 return;
13754         }
13755
13756         if (decalsystem->model != model)
13757                 R_DecalSystem_Reset(decalsystem);
13758         decalsystem->model = model;
13759
13760         RSurf_ActiveModelEntity(ent, false, false, false);
13761
13762         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13763         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13764         VectorNormalize(localnormal);
13765         localsize = worldsize*rsurface.inversematrixscale;
13766         localmins[0] = localorigin[0] - localsize;
13767         localmins[1] = localorigin[1] - localsize;
13768         localmins[2] = localorigin[2] - localsize;
13769         localmaxs[0] = localorigin[0] + localsize;
13770         localmaxs[1] = localorigin[1] + localsize;
13771         localmaxs[2] = localorigin[2] + localsize;
13772
13773         //VectorCopy(localnormal, planes[4]);
13774         //VectorVectors(planes[4], planes[2], planes[0]);
13775         AnglesFromVectors(angles, localnormal, NULL, false);
13776         AngleVectors(angles, planes[0], planes[2], planes[4]);
13777         VectorNegate(planes[0], planes[1]);
13778         VectorNegate(planes[2], planes[3]);
13779         VectorNegate(planes[4], planes[5]);
13780         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13781         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13782         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13783         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13784         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13785         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13786
13787 #if 1
13788 // works
13789 {
13790         matrix4x4_t forwardprojection;
13791         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13792         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13793 }
13794 #else
13795 // broken
13796 {
13797         float projectionvector[4][3];
13798         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13799         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13800         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13801         projectionvector[0][0] = planes[0][0] * ilocalsize;
13802         projectionvector[0][1] = planes[1][0] * ilocalsize;
13803         projectionvector[0][2] = planes[2][0] * ilocalsize;
13804         projectionvector[1][0] = planes[0][1] * ilocalsize;
13805         projectionvector[1][1] = planes[1][1] * ilocalsize;
13806         projectionvector[1][2] = planes[2][1] * ilocalsize;
13807         projectionvector[2][0] = planes[0][2] * ilocalsize;
13808         projectionvector[2][1] = planes[1][2] * ilocalsize;
13809         projectionvector[2][2] = planes[2][2] * ilocalsize;
13810         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13811         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13812         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13813         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13814 }
13815 #endif
13816
13817         dynamic = model->surfmesh.isanimated;
13818         numsurfacelist = model->nummodelsurfaces;
13819         surfacelist = model->sortedmodelsurfaces;
13820         surfaces = model->data_surfaces;
13821
13822         bih = NULL;
13823         bih_triangles_count = -1;
13824         if(!dynamic)
13825         {
13826                 if(model->render_bih.numleafs)
13827                         bih = &model->render_bih;
13828                 else if(model->collision_bih.numleafs)
13829                         bih = &model->collision_bih;
13830         }
13831         if(bih)
13832                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13833         if(bih_triangles_count == 0)
13834                 return;
13835         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13836                 return;
13837         if(bih_triangles_count > 0)
13838         {
13839                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13840                 {
13841                         surfaceindex = bih_surfaces[triangleindex];
13842                         surface = surfaces + surfaceindex;
13843                         texture = surface->texture;
13844                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13845                                 continue;
13846                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13847                                 continue;
13848                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13849                 }
13850         }
13851         else
13852         {
13853                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13854                 {
13855                         surfaceindex = surfacelist[surfacelistindex];
13856                         surface = surfaces + surfaceindex;
13857                         // check cull box first because it rejects more than any other check
13858                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13859                                 continue;
13860                         // skip transparent surfaces
13861                         texture = surface->texture;
13862                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13863                                 continue;
13864                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13865                                 continue;
13866                         numtriangles = surface->num_triangles;
13867                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13868                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13869                 }
13870         }
13871 }
13872
13873 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13874 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)
13875 {
13876         int renderentityindex;
13877         float worldmins[3];
13878         float worldmaxs[3];
13879         entity_render_t *ent;
13880
13881         if (!cl_decals_newsystem.integer)
13882                 return;
13883
13884         worldmins[0] = worldorigin[0] - worldsize;
13885         worldmins[1] = worldorigin[1] - worldsize;
13886         worldmins[2] = worldorigin[2] - worldsize;
13887         worldmaxs[0] = worldorigin[0] + worldsize;
13888         worldmaxs[1] = worldorigin[1] + worldsize;
13889         worldmaxs[2] = worldorigin[2] + worldsize;
13890
13891         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13892
13893         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13894         {
13895                 ent = r_refdef.scene.entities[renderentityindex];
13896                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13897                         continue;
13898
13899                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13900         }
13901 }
13902
13903 typedef struct r_decalsystem_splatqueue_s
13904 {
13905         vec3_t worldorigin;
13906         vec3_t worldnormal;
13907         float color[4];
13908         float tcrange[4];
13909         float worldsize;
13910         int decalsequence;
13911 }
13912 r_decalsystem_splatqueue_t;
13913
13914 int r_decalsystem_numqueued = 0;
13915 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13916
13917 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)
13918 {
13919         r_decalsystem_splatqueue_t *queue;
13920
13921         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13922                 return;
13923
13924         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13925         VectorCopy(worldorigin, queue->worldorigin);
13926         VectorCopy(worldnormal, queue->worldnormal);
13927         Vector4Set(queue->color, r, g, b, a);
13928         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13929         queue->worldsize = worldsize;
13930         queue->decalsequence = cl.decalsequence++;
13931 }
13932
13933 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13934 {
13935         int i;
13936         r_decalsystem_splatqueue_t *queue;
13937
13938         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13939                 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);
13940         r_decalsystem_numqueued = 0;
13941 }
13942
13943 extern cvar_t cl_decals_max;
13944 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13945 {
13946         int i;
13947         decalsystem_t *decalsystem = &ent->decalsystem;
13948         int numdecals;
13949         int killsequence;
13950         tridecal_t *decal;
13951         float frametime;
13952         float lifetime;
13953
13954         if (!decalsystem->numdecals)
13955                 return;
13956
13957         if (r_showsurfaces.integer)
13958                 return;
13959
13960         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13961         {
13962                 R_DecalSystem_Reset(decalsystem);
13963                 return;
13964         }
13965
13966         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13967         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13968
13969         if (decalsystem->lastupdatetime)
13970                 frametime = (cl.time - decalsystem->lastupdatetime);
13971         else
13972                 frametime = 0;
13973         decalsystem->lastupdatetime = cl.time;
13974         decal = decalsystem->decals;
13975         numdecals = decalsystem->numdecals;
13976
13977         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13978         {
13979                 if (decal->color4ub[0][3])
13980                 {
13981                         decal->lived += frametime;
13982                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13983                         {
13984                                 memset(decal, 0, sizeof(*decal));
13985                                 if (decalsystem->freedecal > i)
13986                                         decalsystem->freedecal = i;
13987                         }
13988                 }
13989         }
13990         decal = decalsystem->decals;
13991         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13992                 numdecals--;
13993
13994         // collapse the array by shuffling the tail decals into the gaps
13995         for (;;)
13996         {
13997                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13998                         decalsystem->freedecal++;
13999                 if (decalsystem->freedecal == numdecals)
14000                         break;
14001                 decal[decalsystem->freedecal] = decal[--numdecals];
14002         }
14003
14004         decalsystem->numdecals = numdecals;
14005
14006         if (numdecals <= 0)
14007         {
14008                 // if there are no decals left, reset decalsystem
14009                 R_DecalSystem_Reset(decalsystem);
14010         }
14011 }
14012
14013 extern skinframe_t *decalskinframe;
14014 static void R_DrawModelDecals_Entity(entity_render_t *ent)
14015 {
14016         int i;
14017         decalsystem_t *decalsystem = &ent->decalsystem;
14018         int numdecals;
14019         tridecal_t *decal;
14020         float faderate;
14021         float alpha;
14022         float *v3f;
14023         float *c4f;
14024         float *t2f;
14025         const int *e;
14026         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14027         int numtris = 0;
14028
14029         numdecals = decalsystem->numdecals;
14030         if (!numdecals)
14031                 return;
14032
14033         if (r_showsurfaces.integer)
14034                 return;
14035
14036         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14037         {
14038                 R_DecalSystem_Reset(decalsystem);
14039                 return;
14040         }
14041
14042         // if the model is static it doesn't matter what value we give for
14043         // wantnormals and wanttangents, so this logic uses only rules applicable
14044         // to a model, knowing that they are meaningless otherwise
14045         if (ent == r_refdef.scene.worldentity)
14046                 RSurf_ActiveWorldEntity();
14047         else
14048                 RSurf_ActiveModelEntity(ent, false, false, false);
14049
14050         decalsystem->lastupdatetime = cl.time;
14051         decal = decalsystem->decals;
14052
14053         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14054
14055         // update vertex positions for animated models
14056         v3f = decalsystem->vertex3f;
14057         c4f = decalsystem->color4f;
14058         t2f = decalsystem->texcoord2f;
14059         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14060         {
14061                 if (!decal->color4ub[0][3])
14062                         continue;
14063
14064                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14065                         continue;
14066
14067                 // update color values for fading decals
14068                 if (decal->lived >= cl_decals_time.value)
14069                 {
14070                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14071                         alpha *= (1.0f/255.0f);
14072                 }
14073                 else
14074                         alpha = 1.0f/255.0f;
14075
14076                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14077                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14078                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14079                 c4f[ 3] = 1;
14080                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14081                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14082                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14083                 c4f[ 7] = 1;
14084                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14085                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14086                 c4f[10] = decal->color4ub[2][2] * alpha;
14087                 c4f[11] = 1;
14088
14089                 t2f[0] = decal->texcoord2f[0][0];
14090                 t2f[1] = decal->texcoord2f[0][1];
14091                 t2f[2] = decal->texcoord2f[1][0];
14092                 t2f[3] = decal->texcoord2f[1][1];
14093                 t2f[4] = decal->texcoord2f[2][0];
14094                 t2f[5] = decal->texcoord2f[2][1];
14095
14096                 // update vertex positions for animated models
14097                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14098                 {
14099                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14100                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14101                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14102                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14103                 }
14104                 else
14105                 {
14106                         VectorCopy(decal->vertex3f[0], v3f);
14107                         VectorCopy(decal->vertex3f[1], v3f + 3);
14108                         VectorCopy(decal->vertex3f[2], v3f + 6);
14109                 }
14110
14111                 if (r_refdef.fogenabled)
14112                 {
14113                         alpha = RSurf_FogVertex(v3f);
14114                         VectorScale(c4f, alpha, c4f);
14115                         alpha = RSurf_FogVertex(v3f + 3);
14116                         VectorScale(c4f + 4, alpha, c4f + 4);
14117                         alpha = RSurf_FogVertex(v3f + 6);
14118                         VectorScale(c4f + 8, alpha, c4f + 8);
14119                 }
14120
14121                 v3f += 9;
14122                 c4f += 12;
14123                 t2f += 6;
14124                 numtris++;
14125         }
14126
14127         if (numtris > 0)
14128         {
14129                 r_refdef.stats.drawndecals += numtris;
14130
14131                 // now render the decals all at once
14132                 // (this assumes they all use one particle font texture!)
14133                 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);
14134 //              R_Mesh_ResetTextureState();
14135                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14136                 GL_DepthMask(false);
14137                 GL_DepthRange(0, 1);
14138                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14139                 GL_DepthTest(true);
14140                 GL_CullFace(GL_NONE);
14141                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14142                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14143                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14144         }
14145 }
14146
14147 static void R_DrawModelDecals(void)
14148 {
14149         int i, numdecals;
14150
14151         // fade faster when there are too many decals
14152         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14153         for (i = 0;i < r_refdef.scene.numentities;i++)
14154                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14155
14156         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14157         for (i = 0;i < r_refdef.scene.numentities;i++)
14158                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14159                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14160
14161         R_DecalSystem_ApplySplatEntitiesQueue();
14162
14163         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14164         for (i = 0;i < r_refdef.scene.numentities;i++)
14165                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14166
14167         r_refdef.stats.totaldecals += numdecals;
14168
14169         if (r_showsurfaces.integer)
14170                 return;
14171
14172         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14173
14174         for (i = 0;i < r_refdef.scene.numentities;i++)
14175         {
14176                 if (!r_refdef.viewcache.entityvisible[i])
14177                         continue;
14178                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14179                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14180         }
14181 }
14182
14183 extern cvar_t mod_collision_bih;
14184 void R_DrawDebugModel(void)
14185 {
14186         entity_render_t *ent = rsurface.entity;
14187         int i, j, k, l, flagsmask;
14188         const msurface_t *surface;
14189         dp_model_t *model = ent->model;
14190         vec3_t v;
14191
14192         switch(vid.renderpath)
14193         {
14194         case RENDERPATH_GL11:
14195         case RENDERPATH_GL13:
14196         case RENDERPATH_GL20:
14197         case RENDERPATH_CGGL:
14198                 break;
14199         case RENDERPATH_D3D9:
14200                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14201                 return;
14202         case RENDERPATH_D3D10:
14203                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14204                 return;
14205         case RENDERPATH_D3D11:
14206                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14207                 return;
14208         }
14209
14210         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14211
14212 //      R_Mesh_ResetTextureState();
14213         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14214         GL_DepthRange(0, 1);
14215         GL_DepthTest(!r_showdisabledepthtest.integer);
14216         GL_DepthMask(false);
14217         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14218
14219         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14220         {
14221                 int triangleindex;
14222                 int bihleafindex;
14223                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14224                 const q3mbrush_t *brush;
14225                 const bih_t *bih = &model->collision_bih;
14226                 const bih_leaf_t *bihleaf;
14227                 float vertex3f[3][3];
14228                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14229                 cullbox = false;
14230                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14231                 {
14232                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14233                                 continue;
14234                         switch (bihleaf->type)
14235                         {
14236                         case BIH_BRUSH:
14237                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14238                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14239                                 {
14240                                         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);
14241                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14242                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14243                                 }
14244                                 break;
14245                         case BIH_COLLISIONTRIANGLE:
14246                                 triangleindex = bihleaf->itemindex;
14247                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14248                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14249                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14250                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
14251                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14252                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14253                                 break;
14254                         case BIH_RENDERTRIANGLE:
14255                                 triangleindex = bihleaf->itemindex;
14256                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14257                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14258                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14259                                 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);
14260                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14261                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14262                                 break;
14263                         }
14264                 }
14265         }
14266
14267         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14268
14269         if (r_showtris.integer || (r_shownormals.value != 0))
14270         {
14271                 if (r_showdisabledepthtest.integer)
14272                 {
14273                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14274                         GL_DepthMask(false);
14275                 }
14276                 else
14277                 {
14278                         GL_BlendFunc(GL_ONE, GL_ZERO);
14279                         GL_DepthMask(true);
14280                 }
14281                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14282                 {
14283                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14284                                 continue;
14285                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14286                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14287                         {
14288                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14289                                 if (r_showtris.value > 0)
14290                                 {
14291                                         if (!rsurface.texture->currentlayers->depthmask)
14292                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14293                                         else if (ent == r_refdef.scene.worldentity)
14294                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14295                                         else
14296                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14297                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14298                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14299                                         RSurf_DrawBatch();
14300                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14301                                         CHECKGLERROR
14302                                 }
14303                                 if (r_shownormals.value < 0)
14304                                 {
14305                                         qglBegin(GL_LINES);
14306                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14307                                         {
14308                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14309                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14310                                                 qglVertex3f(v[0], v[1], v[2]);
14311                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14312                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14313                                                 qglVertex3f(v[0], v[1], v[2]);
14314                                         }
14315                                         qglEnd();
14316                                         CHECKGLERROR
14317                                 }
14318                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14319                                 {
14320                                         qglBegin(GL_LINES);
14321                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14322                                         {
14323                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14324                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14325                                                 qglVertex3f(v[0], v[1], v[2]);
14326                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14327                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14328                                                 qglVertex3f(v[0], v[1], v[2]);
14329                                         }
14330                                         qglEnd();
14331                                         CHECKGLERROR
14332                                         qglBegin(GL_LINES);
14333                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14334                                         {
14335                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14336                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14337                                                 qglVertex3f(v[0], v[1], v[2]);
14338                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14339                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14340                                                 qglVertex3f(v[0], v[1], v[2]);
14341                                         }
14342                                         qglEnd();
14343                                         CHECKGLERROR
14344                                         qglBegin(GL_LINES);
14345                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14346                                         {
14347                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14348                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14349                                                 qglVertex3f(v[0], v[1], v[2]);
14350                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14351                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14352                                                 qglVertex3f(v[0], v[1], v[2]);
14353                                         }
14354                                         qglEnd();
14355                                         CHECKGLERROR
14356                                 }
14357                         }
14358                 }
14359                 rsurface.texture = NULL;
14360         }
14361 }
14362
14363 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14364 int r_maxsurfacelist = 0;
14365 const msurface_t **r_surfacelist = NULL;
14366 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14367 {
14368         int i, j, endj, flagsmask;
14369         dp_model_t *model = r_refdef.scene.worldmodel;
14370         msurface_t *surfaces;
14371         unsigned char *update;
14372         int numsurfacelist = 0;
14373         if (model == NULL)
14374                 return;
14375
14376         if (r_maxsurfacelist < model->num_surfaces)
14377         {
14378                 r_maxsurfacelist = model->num_surfaces;
14379                 if (r_surfacelist)
14380                         Mem_Free((msurface_t**)r_surfacelist);
14381                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14382         }
14383
14384         RSurf_ActiveWorldEntity();
14385
14386         surfaces = model->data_surfaces;
14387         update = model->brushq1.lightmapupdateflags;
14388
14389         // update light styles on this submodel
14390         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14391         {
14392                 model_brush_lightstyleinfo_t *style;
14393                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14394                 {
14395                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14396                         {
14397                                 int *list = style->surfacelist;
14398                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14399                                 for (j = 0;j < style->numsurfaces;j++)
14400                                         update[list[j]] = true;
14401                         }
14402                 }
14403         }
14404
14405         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14406
14407         if (debug)
14408         {
14409                 R_DrawDebugModel();
14410                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14411                 return;
14412         }
14413
14414         rsurface.lightmaptexture = NULL;
14415         rsurface.deluxemaptexture = NULL;
14416         rsurface.uselightmaptexture = false;
14417         rsurface.texture = NULL;
14418         rsurface.rtlight = NULL;
14419         numsurfacelist = 0;
14420         // add visible surfaces to draw list
14421         for (i = 0;i < model->nummodelsurfaces;i++)
14422         {
14423                 j = model->sortedmodelsurfaces[i];
14424                 if (r_refdef.viewcache.world_surfacevisible[j])
14425                         r_surfacelist[numsurfacelist++] = surfaces + j;
14426         }
14427         // update lightmaps if needed
14428         if (model->brushq1.firstrender)
14429         {
14430                 model->brushq1.firstrender = false;
14431                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14432                         if (update[j])
14433                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14434         }
14435         else if (update)
14436         {
14437                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14438                         if (r_refdef.viewcache.world_surfacevisible[j])
14439                                 if (update[j])
14440                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14441         }
14442         // don't do anything if there were no surfaces
14443         if (!numsurfacelist)
14444         {
14445                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14446                 return;
14447         }
14448         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14449         GL_AlphaTest(false);
14450
14451         // add to stats if desired
14452         if (r_speeds.integer && !skysurfaces && !depthonly)
14453         {
14454                 r_refdef.stats.world_surfaces += numsurfacelist;
14455                 for (j = 0;j < numsurfacelist;j++)
14456                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14457         }
14458
14459         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14460 }
14461
14462 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14463 {
14464         int i, j, endj, flagsmask;
14465         dp_model_t *model = ent->model;
14466         msurface_t *surfaces;
14467         unsigned char *update;
14468         int numsurfacelist = 0;
14469         if (model == NULL)
14470                 return;
14471
14472         if (r_maxsurfacelist < model->num_surfaces)
14473         {
14474                 r_maxsurfacelist = model->num_surfaces;
14475                 if (r_surfacelist)
14476                         Mem_Free((msurface_t **)r_surfacelist);
14477                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14478         }
14479
14480         // if the model is static it doesn't matter what value we give for
14481         // wantnormals and wanttangents, so this logic uses only rules applicable
14482         // to a model, knowing that they are meaningless otherwise
14483         if (ent == r_refdef.scene.worldentity)
14484                 RSurf_ActiveWorldEntity();
14485         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14486                 RSurf_ActiveModelEntity(ent, false, false, false);
14487         else if (prepass)
14488                 RSurf_ActiveModelEntity(ent, true, true, true);
14489         else if (depthonly)
14490         {
14491                 switch (vid.renderpath)
14492                 {
14493                 case RENDERPATH_GL20:
14494                 case RENDERPATH_CGGL:
14495                 case RENDERPATH_D3D9:
14496                 case RENDERPATH_D3D10:
14497                 case RENDERPATH_D3D11:
14498                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14499                         break;
14500                 case RENDERPATH_GL13:
14501                 case RENDERPATH_GL11:
14502                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14503                         break;
14504                 }
14505         }
14506         else
14507         {
14508                 switch (vid.renderpath)
14509                 {
14510                 case RENDERPATH_GL20:
14511                 case RENDERPATH_CGGL:
14512                 case RENDERPATH_D3D9:
14513                 case RENDERPATH_D3D10:
14514                 case RENDERPATH_D3D11:
14515                         RSurf_ActiveModelEntity(ent, true, true, false);
14516                         break;
14517                 case RENDERPATH_GL13:
14518                 case RENDERPATH_GL11:
14519                         RSurf_ActiveModelEntity(ent, true, false, false);
14520                         break;
14521                 }
14522         }
14523
14524         surfaces = model->data_surfaces;
14525         update = model->brushq1.lightmapupdateflags;
14526
14527         // update light styles
14528         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14529         {
14530                 model_brush_lightstyleinfo_t *style;
14531                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14532                 {
14533                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14534                         {
14535                                 int *list = style->surfacelist;
14536                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14537                                 for (j = 0;j < style->numsurfaces;j++)
14538                                         update[list[j]] = true;
14539                         }
14540                 }
14541         }
14542
14543         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14544
14545         if (debug)
14546         {
14547                 R_DrawDebugModel();
14548                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14549                 return;
14550         }
14551
14552         rsurface.lightmaptexture = NULL;
14553         rsurface.deluxemaptexture = NULL;
14554         rsurface.uselightmaptexture = false;
14555         rsurface.texture = NULL;
14556         rsurface.rtlight = NULL;
14557         numsurfacelist = 0;
14558         // add visible surfaces to draw list
14559         for (i = 0;i < model->nummodelsurfaces;i++)
14560                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14561         // don't do anything if there were no surfaces
14562         if (!numsurfacelist)
14563         {
14564                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14565                 return;
14566         }
14567         // update lightmaps if needed
14568         if (update)
14569         {
14570                 int updated = 0;
14571                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14572                 {
14573                         if (update[j])
14574                         {
14575                                 updated++;
14576                                 R_BuildLightMap(ent, surfaces + j);
14577                         }
14578                 }
14579         }
14580         if (update)
14581                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14582                         if (update[j])
14583                                 R_BuildLightMap(ent, surfaces + j);
14584         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14585         GL_AlphaTest(false);
14586
14587         // add to stats if desired
14588         if (r_speeds.integer && !skysurfaces && !depthonly)
14589         {
14590                 r_refdef.stats.entities_surfaces += numsurfacelist;
14591                 for (j = 0;j < numsurfacelist;j++)
14592                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14593         }
14594
14595         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14596 }
14597
14598 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14599 {
14600         static texture_t texture;
14601         static msurface_t surface;
14602         const msurface_t *surfacelist = &surface;
14603
14604         // fake enough texture and surface state to render this geometry
14605
14606         texture.update_lastrenderframe = -1; // regenerate this texture
14607         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14608         texture.currentskinframe = skinframe;
14609         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14610         texture.offsetmapping = OFFSETMAPPING_OFF;
14611         texture.offsetscale = 1;
14612         texture.specularscalemod = 1;
14613         texture.specularpowermod = 1;
14614
14615         surface.texture = &texture;
14616         surface.num_triangles = numtriangles;
14617         surface.num_firsttriangle = firsttriangle;
14618         surface.num_vertices = numvertices;
14619         surface.num_firstvertex = firstvertex;
14620
14621         // now render it
14622         rsurface.texture = R_GetCurrentTexture(surface.texture);
14623         rsurface.lightmaptexture = NULL;
14624         rsurface.deluxemaptexture = NULL;
14625         rsurface.uselightmaptexture = false;
14626         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14627 }
14628
14629 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)
14630 {
14631         static msurface_t surface;
14632         const msurface_t *surfacelist = &surface;
14633
14634         // fake enough texture and surface state to render this geometry
14635         surface.texture = texture;
14636         surface.num_triangles = numtriangles;
14637         surface.num_firsttriangle = firsttriangle;
14638         surface.num_vertices = numvertices;
14639         surface.num_firstvertex = firstvertex;
14640
14641         // now render it
14642         rsurface.texture = R_GetCurrentTexture(surface.texture);
14643         rsurface.lightmaptexture = NULL;
14644         rsurface.deluxemaptexture = NULL;
14645         rsurface.uselightmaptexture = false;
14646         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14647 }