]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
add r_glsl_saturation_redcompensate optional effect to r_glsl_saturate (only works...
[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
152 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)"};
153 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
154 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"};
155 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
156 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
157 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
158
159 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
160 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
161 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
162 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
163
164 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
165 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
166 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
167 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
168 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
169 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
170 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
171
172 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
173 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
174 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
175 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)"};
176
177 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"};
178
179 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"};
180
181 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
182
183 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
184 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"};
185 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
186 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
187 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
188 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
189 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
190
191 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
192 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"};
193
194 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)"};
195
196 extern cvar_t v_glslgamma;
197
198 extern qboolean v_flipped_state;
199
200 static struct r_bloomstate_s
201 {
202         qboolean enabled;
203         qboolean hdr;
204
205         int bloomwidth, bloomheight;
206
207         int screentexturewidth, screentextureheight;
208         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
209
210         int bloomtexturewidth, bloomtextureheight;
211         rtexture_t *texture_bloom;
212
213         // arrays for rendering the screen passes
214         float screentexcoord2f[8];
215         float bloomtexcoord2f[8];
216         float offsettexcoord2f[8];
217
218         r_viewport_t viewport;
219 }
220 r_bloomstate;
221
222 r_waterstate_t r_waterstate;
223
224 /// shadow volume bsp struct with automatically growing nodes buffer
225 svbsp_t r_svbsp;
226
227 rtexture_t *r_texture_blanknormalmap;
228 rtexture_t *r_texture_white;
229 rtexture_t *r_texture_grey128;
230 rtexture_t *r_texture_black;
231 rtexture_t *r_texture_notexture;
232 rtexture_t *r_texture_whitecube;
233 rtexture_t *r_texture_normalizationcube;
234 rtexture_t *r_texture_fogattenuation;
235 rtexture_t *r_texture_fogheighttexture;
236 rtexture_t *r_texture_gammaramps;
237 unsigned int r_texture_gammaramps_serial;
238 //rtexture_t *r_texture_fogintensity;
239 rtexture_t *r_texture_reflectcube;
240
241 // TODO: hash lookups?
242 typedef struct cubemapinfo_s
243 {
244         char basename[64];
245         rtexture_t *texture;
246 }
247 cubemapinfo_t;
248
249 int r_texture_numcubemaps;
250 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
251
252 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
253 unsigned int r_numqueries;
254 unsigned int r_maxqueries;
255
256 typedef struct r_qwskincache_s
257 {
258         char name[MAX_QPATH];
259         skinframe_t *skinframe;
260 }
261 r_qwskincache_t;
262
263 static r_qwskincache_t *r_qwskincache;
264 static int r_qwskincache_size;
265
266 /// vertex coordinates for a quad that covers the screen exactly
267 extern const float r_screenvertex3f[12];
268 extern const float r_d3dscreenvertex3f[12];
269 const float r_screenvertex3f[12] =
270 {
271         0, 0, 0,
272         1, 0, 0,
273         1, 1, 0,
274         0, 1, 0
275 };
276 const float r_d3dscreenvertex3f[12] =
277 {
278         0, 1, 0,
279         1, 1, 0,
280         1, 0, 0,
281         0, 0, 0
282 };
283
284 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
285 {
286         int i;
287         for (i = 0;i < verts;i++)
288         {
289                 out[0] = in[0] * r;
290                 out[1] = in[1] * g;
291                 out[2] = in[2] * b;
292                 out[3] = in[3];
293                 in += 4;
294                 out += 4;
295         }
296 }
297
298 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
299 {
300         int i;
301         for (i = 0;i < verts;i++)
302         {
303                 out[0] = r;
304                 out[1] = g;
305                 out[2] = b;
306                 out[3] = a;
307                 out += 4;
308         }
309 }
310
311 // FIXME: move this to client?
312 void FOG_clear(void)
313 {
314         if (gamemode == GAME_NEHAHRA)
315         {
316                 Cvar_Set("gl_fogenable", "0");
317                 Cvar_Set("gl_fogdensity", "0.2");
318                 Cvar_Set("gl_fogred", "0.3");
319                 Cvar_Set("gl_foggreen", "0.3");
320                 Cvar_Set("gl_fogblue", "0.3");
321         }
322         r_refdef.fog_density = 0;
323         r_refdef.fog_red = 0;
324         r_refdef.fog_green = 0;
325         r_refdef.fog_blue = 0;
326         r_refdef.fog_alpha = 1;
327         r_refdef.fog_start = 0;
328         r_refdef.fog_end = 16384;
329         r_refdef.fog_height = 1<<30;
330         r_refdef.fog_fadedepth = 128;
331         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
332 }
333
334 static void R_BuildBlankTextures(void)
335 {
336         unsigned char data[4];
337         data[2] = 128; // normal X
338         data[1] = 128; // normal Y
339         data[0] = 255; // normal Z
340         data[3] = 128; // height
341         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
342         data[0] = 255;
343         data[1] = 255;
344         data[2] = 255;
345         data[3] = 255;
346         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
347         data[0] = 128;
348         data[1] = 128;
349         data[2] = 128;
350         data[3] = 255;
351         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
352         data[0] = 0;
353         data[1] = 0;
354         data[2] = 0;
355         data[3] = 255;
356         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
357 }
358
359 static void R_BuildNoTexture(void)
360 {
361         int x, y;
362         unsigned char pix[16][16][4];
363         // this makes a light grey/dark grey checkerboard texture
364         for (y = 0;y < 16;y++)
365         {
366                 for (x = 0;x < 16;x++)
367                 {
368                         if ((y < 8) ^ (x < 8))
369                         {
370                                 pix[y][x][0] = 128;
371                                 pix[y][x][1] = 128;
372                                 pix[y][x][2] = 128;
373                                 pix[y][x][3] = 255;
374                         }
375                         else
376                         {
377                                 pix[y][x][0] = 64;
378                                 pix[y][x][1] = 64;
379                                 pix[y][x][2] = 64;
380                                 pix[y][x][3] = 255;
381                         }
382                 }
383         }
384         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildWhiteCube(void)
388 {
389         unsigned char data[6*1*1*4];
390         memset(data, 255, sizeof(data));
391         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
392 }
393
394 static void R_BuildNormalizationCube(void)
395 {
396         int x, y, side;
397         vec3_t v;
398         vec_t s, t, intensity;
399 #define NORMSIZE 64
400         unsigned char *data;
401         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
402         for (side = 0;side < 6;side++)
403         {
404                 for (y = 0;y < NORMSIZE;y++)
405                 {
406                         for (x = 0;x < NORMSIZE;x++)
407                         {
408                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
409                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
410                                 switch(side)
411                                 {
412                                 default:
413                                 case 0:
414                                         v[0] = 1;
415                                         v[1] = -t;
416                                         v[2] = -s;
417                                         break;
418                                 case 1:
419                                         v[0] = -1;
420                                         v[1] = -t;
421                                         v[2] = s;
422                                         break;
423                                 case 2:
424                                         v[0] = s;
425                                         v[1] = 1;
426                                         v[2] = t;
427                                         break;
428                                 case 3:
429                                         v[0] = s;
430                                         v[1] = -1;
431                                         v[2] = -t;
432                                         break;
433                                 case 4:
434                                         v[0] = s;
435                                         v[1] = -t;
436                                         v[2] = 1;
437                                         break;
438                                 case 5:
439                                         v[0] = -s;
440                                         v[1] = -t;
441                                         v[2] = -1;
442                                         break;
443                                 }
444                                 intensity = 127.0f / sqrt(DotProduct(v, v));
445                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
446                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
447                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
448                                 data[((side*64+y)*64+x)*4+3] = 255;
449                         }
450                 }
451         }
452         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
453         Mem_Free(data);
454 }
455
456 static void R_BuildFogTexture(void)
457 {
458         int x, b;
459 #define FOGWIDTH 256
460         unsigned char data1[FOGWIDTH][4];
461         //unsigned char data2[FOGWIDTH][4];
462         double d, r, alpha;
463
464         r_refdef.fogmasktable_start = r_refdef.fog_start;
465         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
466         r_refdef.fogmasktable_range = r_refdef.fogrange;
467         r_refdef.fogmasktable_density = r_refdef.fog_density;
468
469         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
470         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
471         {
472                 d = (x * r - r_refdef.fogmasktable_start);
473                 if(developer_extra.integer)
474                         Con_DPrintf("%f ", d);
475                 d = max(0, d);
476                 if (r_fog_exp2.integer)
477                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
478                 else
479                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
480                 if(developer_extra.integer)
481                         Con_DPrintf(" : %f ", alpha);
482                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
483                 if(developer_extra.integer)
484                         Con_DPrintf(" = %f\n", alpha);
485                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
486         }
487
488         for (x = 0;x < FOGWIDTH;x++)
489         {
490                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
491                 data1[x][0] = b;
492                 data1[x][1] = b;
493                 data1[x][2] = b;
494                 data1[x][3] = 255;
495                 //data2[x][0] = 255 - b;
496                 //data2[x][1] = 255 - b;
497                 //data2[x][2] = 255 - b;
498                 //data2[x][3] = 255;
499         }
500         if (r_texture_fogattenuation)
501         {
502                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
503                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
504         }
505         else
506         {
507                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
508                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
509         }
510 }
511
512 static void R_BuildFogHeightTexture(void)
513 {
514         unsigned char *inpixels;
515         int size;
516         int x;
517         int y;
518         int j;
519         float c[4];
520         float f;
521         inpixels = NULL;
522         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
523         if (r_refdef.fogheighttexturename[0])
524                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
525         if (!inpixels)
526         {
527                 r_refdef.fog_height_tablesize = 0;
528                 if (r_texture_fogheighttexture)
529                         R_FreeTexture(r_texture_fogheighttexture);
530                 r_texture_fogheighttexture = NULL;
531                 if (r_refdef.fog_height_table2d)
532                         Mem_Free(r_refdef.fog_height_table2d);
533                 r_refdef.fog_height_table2d = NULL;
534                 if (r_refdef.fog_height_table1d)
535                         Mem_Free(r_refdef.fog_height_table1d);
536                 r_refdef.fog_height_table1d = NULL;
537                 return;
538         }
539         size = image_width;
540         r_refdef.fog_height_tablesize = size;
541         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
542         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
543         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
544         Mem_Free(inpixels);
545         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
546         // average fog color table accounting for every fog layer between a point
547         // and the camera.  (Note: attenuation is handled separately!)
548         for (y = 0;y < size;y++)
549         {
550                 for (x = 0;x < size;x++)
551                 {
552                         Vector4Clear(c);
553                         f = 0;
554                         if (x < y)
555                         {
556                                 for (j = x;j <= y;j++)
557                                 {
558                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
559                                         f++;
560                                 }
561                         }
562                         else
563                         {
564                                 for (j = x;j >= y;j--)
565                                 {
566                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
567                                         f++;
568                                 }
569                         }
570                         f = 1.0f / f;
571                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
572                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
573                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
574                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
575                 }
576         }
577         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
578 }
579
580 //=======================================================================================================================================================
581
582 static const char *builtinshaderstring =
583 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
584 "// written by Forest 'LordHavoc' Hale\n"
585 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
586 "\n"
587 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
588 "# define USEFOG\n"
589 "#endif\n"
590 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
591 "#define USELIGHTMAP\n"
592 "#endif\n"
593 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
594 "#define USEEYEVECTOR\n"
595 "#endif\n"
596 "\n"
597 "#ifdef USESHADOWMAP2D\n"
598 "# ifdef GL_EXT_gpu_shader4\n"
599 "#   extension GL_EXT_gpu_shader4 : enable\n"
600 "# endif\n"
601 "# ifdef GL_ARB_texture_gather\n"
602 "#   extension GL_ARB_texture_gather : enable\n"
603 "# else\n"
604 "#   ifdef GL_AMD_texture_texture4\n"
605 "#     extension GL_AMD_texture_texture4 : enable\n"
606 "#   endif\n"
607 "# endif\n"
608 "#endif\n"
609 "\n"
610 "//#ifdef USESHADOWSAMPLER\n"
611 "//# extension GL_ARB_shadow : enable\n"
612 "//#endif\n"
613 "\n"
614 "//#ifdef __GLSL_CG_DATA_TYPES\n"
615 "//# define myhalf half\n"
616 "//# define myhalf2 half2\n"
617 "//# define myhalf3 half3\n"
618 "//# define myhalf4 half4\n"
619 "//#else\n"
620 "# define myhalf float\n"
621 "# define myhalf2 vec2\n"
622 "# define myhalf3 vec3\n"
623 "# define myhalf4 vec4\n"
624 "//#endif\n"
625 "\n"
626 "#ifdef VERTEX_SHADER\n"
627 "uniform mat4 ModelViewProjectionMatrix;\n"
628 "#endif\n"
629 "\n"
630 "#ifdef MODE_DEPTH_OR_SHADOW\n"
631 "#ifdef VERTEX_SHADER\n"
632 "void main(void)\n"
633 "{\n"
634 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
635 "}\n"
636 "#endif\n"
637 "#else // !MODE_DEPTH_ORSHADOW\n"
638 "\n"
639 "\n"
640 "\n"
641 "\n"
642 "#ifdef MODE_SHOWDEPTH\n"
643 "#ifdef VERTEX_SHADER\n"
644 "void main(void)\n"
645 "{\n"
646 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
647 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
648 "}\n"
649 "#endif\n"
650 "\n"
651 "#ifdef FRAGMENT_SHADER\n"
652 "void main(void)\n"
653 "{\n"
654 "       gl_FragColor = gl_Color;\n"
655 "}\n"
656 "#endif\n"
657 "#else // !MODE_SHOWDEPTH\n"
658 "\n"
659 "\n"
660 "\n"
661 "\n"
662 "#ifdef MODE_POSTPROCESS\n"
663 "varying vec2 TexCoord1;\n"
664 "varying vec2 TexCoord2;\n"
665 "\n"
666 "#ifdef VERTEX_SHADER\n"
667 "void main(void)\n"
668 "{\n"
669 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
670 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
671 "#ifdef USEBLOOM\n"
672 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
673 "#endif\n"
674 "}\n"
675 "#endif\n"
676 "\n"
677 "#ifdef FRAGMENT_SHADER\n"
678 "uniform sampler2D Texture_First;\n"
679 "#ifdef USEBLOOM\n"
680 "uniform sampler2D Texture_Second;\n"
681 "uniform vec4 BloomColorSubtract;\n"
682 "#endif\n"
683 "#ifdef USEGAMMARAMPS\n"
684 "uniform sampler2D Texture_GammaRamps;\n"
685 "#endif\n"
686 "#ifdef USESATURATION\n"
687 "uniform float Saturation;\n"
688 "#endif\n"
689 "#ifdef USEVIEWTINT\n"
690 "uniform vec4 ViewTintColor;\n"
691 "#endif\n"
692 "//uncomment these if you want to use them:\n"
693 "uniform vec4 UserVec1;\n"
694 "uniform vec4 UserVec2;\n"
695 "// uniform vec4 UserVec3;\n"
696 "// uniform vec4 UserVec4;\n"
697 "// uniform float ClientTime;\n"
698 "uniform vec2 PixelSize;\n"
699 "void main(void)\n"
700 "{\n"
701 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
702 "#ifdef USEBLOOM\n"
703 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
704 "#endif\n"
705 "#ifdef USEVIEWTINT\n"
706 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
707 "#endif\n"
708 "\n"
709 "#ifdef USEPOSTPROCESSING\n"
710 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
711 "// 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"
712 "       float sobel = 1.0;\n"
713 "       // vec2 ts = textureSize(Texture_First, 0);\n"
714 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
715 "       vec2 px = PixelSize;\n"
716 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
717 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
718 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
719 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
720 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
721 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
722 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
723 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
724 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
725 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
726 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
727 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
728 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
729 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
730 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
731 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
732 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
733 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
734 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
735 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
736 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
737 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
738 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
739 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
740 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
741 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
742 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
743 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
744 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
745 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
746 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
747 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
748 "#endif\n"
749 "\n"
750 "#ifdef USESATURATION\n"
751 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
752 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
753 "       // 'vampire sight' effect, wheres red is compensated\n"
754 "       #ifdef SATURATION_REDCOMPENSATE\n"
755 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
756 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
757 "               gl_FragColor.r += rboost;\n"
758 "       #else\n"
759 "               // normal desaturation\n"
760 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
761 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
762 "       #endif\n"
763 "#endif\n"
764 "\n"
765 "#ifdef USEGAMMARAMPS\n"
766 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
767 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
768 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
769 "#endif\n"
770 "}\n"
771 "#endif\n"
772 "#else // !MODE_POSTPROCESS\n"
773 "\n"
774 "\n"
775 "\n"
776 "\n"
777 "#ifdef MODE_GENERIC\n"
778 "#ifdef USEDIFFUSE\n"
779 "varying vec2 TexCoord1;\n"
780 "#endif\n"
781 "#ifdef USESPECULAR\n"
782 "varying vec2 TexCoord2;\n"
783 "#endif\n"
784 "#ifdef VERTEX_SHADER\n"
785 "void main(void)\n"
786 "{\n"
787 "       gl_FrontColor = gl_Color;\n"
788 "#ifdef USEDIFFUSE\n"
789 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
790 "#endif\n"
791 "#ifdef USESPECULAR\n"
792 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
793 "#endif\n"
794 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
795 "}\n"
796 "#endif\n"
797 "\n"
798 "#ifdef FRAGMENT_SHADER\n"
799 "#ifdef USEDIFFUSE\n"
800 "uniform sampler2D Texture_First;\n"
801 "#endif\n"
802 "#ifdef USESPECULAR\n"
803 "uniform sampler2D Texture_Second;\n"
804 "#endif\n"
805 "\n"
806 "void main(void)\n"
807 "{\n"
808 "       gl_FragColor = gl_Color;\n"
809 "#ifdef USEDIFFUSE\n"
810 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
811 "#endif\n"
812 "\n"
813 "#ifdef USESPECULAR\n"
814 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
815 "# ifdef USECOLORMAPPING\n"
816 "       gl_FragColor *= tex2;\n"
817 "# endif\n"
818 "# ifdef USEGLOW\n"
819 "       gl_FragColor += tex2;\n"
820 "# endif\n"
821 "# ifdef USEVERTEXTEXTUREBLEND\n"
822 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
823 "# endif\n"
824 "#endif\n"
825 "}\n"
826 "#endif\n"
827 "#else // !MODE_GENERIC\n"
828 "\n"
829 "\n"
830 "\n"
831 "\n"
832 "#ifdef MODE_BLOOMBLUR\n"
833 "varying TexCoord;\n"
834 "#ifdef VERTEX_SHADER\n"
835 "void main(void)\n"
836 "{\n"
837 "       gl_FrontColor = gl_Color;\n"
838 "       TexCoord = gl_MultiTexCoord0.xy;\n"
839 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
840 "}\n"
841 "#endif\n"
842 "\n"
843 "#ifdef FRAGMENT_SHADER\n"
844 "uniform sampler2D Texture_First;\n"
845 "uniform vec4 BloomBlur_Parameters;\n"
846 "\n"
847 "void main(void)\n"
848 "{\n"
849 "       int i;\n"
850 "       vec2 tc = TexCoord;\n"
851 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
852 "       tc += BloomBlur_Parameters.xy;\n"
853 "       for (i = 1;i < SAMPLES;i++)\n"
854 "       {\n"
855 "               color += texture2D(Texture_First, tc).rgb;\n"
856 "               tc += BloomBlur_Parameters.xy;\n"
857 "       }\n"
858 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
859 "}\n"
860 "#endif\n"
861 "#else // !MODE_BLOOMBLUR\n"
862 "#ifdef MODE_REFRACTION\n"
863 "varying vec2 TexCoord;\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "uniform mat4 TexMatrix;\n"
866 "#ifdef VERTEX_SHADER\n"
867 "\n"
868 "void main(void)\n"
869 "{\n"
870 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
871 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
872 "       ModelViewProjectionPosition = gl_Position;\n"
873 "}\n"
874 "#endif\n"
875 "\n"
876 "#ifdef FRAGMENT_SHADER\n"
877 "uniform sampler2D Texture_Normal;\n"
878 "uniform sampler2D Texture_Refraction;\n"
879 "uniform sampler2D Texture_Reflection;\n"
880 "\n"
881 "uniform vec4 DistortScaleRefractReflect;\n"
882 "uniform vec4 ScreenScaleRefractReflect;\n"
883 "uniform vec4 ScreenCenterRefractReflect;\n"
884 "uniform vec4 RefractColor;\n"
885 "uniform vec4 ReflectColor;\n"
886 "uniform float ReflectFactor;\n"
887 "uniform float ReflectOffset;\n"
888 "\n"
889 "void main(void)\n"
890 "{\n"
891 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
892 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
893 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
894 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
895 "       // FIXME temporary hack to detect the case that the reflection\n"
896 "       // gets blackened at edges due to leaving the area that contains actual\n"
897 "       // content.\n"
898 "       // Remove this 'ack once we have a better way to stop this thing from\n"
899 "       // 'appening.\n"
900 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
901 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
902 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
903 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
904 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
905 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
906 "}\n"
907 "#endif\n"
908 "#else // !MODE_REFRACTION\n"
909 "\n"
910 "\n"
911 "\n"
912 "\n"
913 "#ifdef MODE_WATER\n"
914 "varying vec2 TexCoord;\n"
915 "varying vec3 EyeVector;\n"
916 "varying vec4 ModelViewProjectionPosition;\n"
917 "#ifdef VERTEX_SHADER\n"
918 "uniform vec3 EyePosition;\n"
919 "uniform mat4 TexMatrix;\n"
920 "\n"
921 "void main(void)\n"
922 "{\n"
923 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
924 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
925 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
926 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
927 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
928 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
929 "       ModelViewProjectionPosition = gl_Position;\n"
930 "}\n"
931 "#endif\n"
932 "\n"
933 "#ifdef FRAGMENT_SHADER\n"
934 "uniform sampler2D Texture_Normal;\n"
935 "uniform sampler2D Texture_Refraction;\n"
936 "uniform sampler2D Texture_Reflection;\n"
937 "\n"
938 "uniform vec4 DistortScaleRefractReflect;\n"
939 "uniform vec4 ScreenScaleRefractReflect;\n"
940 "uniform vec4 ScreenCenterRefractReflect;\n"
941 "uniform vec4 RefractColor;\n"
942 "uniform vec4 ReflectColor;\n"
943 "uniform float ReflectFactor;\n"
944 "uniform float ReflectOffset;\n"
945 "uniform float ClientTime;\n"
946 "\n"
947 "void main(void)\n"
948 "{\n"
949 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
950 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
951 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
952 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
953 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
954 "       vec3 normal = texture2D(Texture_Normal, TexCoord + vec2(0.08, 0.08)*ClientTime*0.5).rgb - vec3(1.0);\n"
955 "       normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime)*0.75).rgb;\n"
956 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
957 "       // FIXME temporary hack to detect the case that the reflection\n"
958 "       // gets blackened at edges due to leaving the area that contains actual\n"
959 "       // content.\n"
960 "       // Remove this 'ack once we have a better way to stop this thing from\n"
961 "       // 'appening.\n"
962 "       float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
963 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
964 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
965 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
966 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
967 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
968 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
969 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
970 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
971 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
972 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
973 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
974 "       gl_FragColor.a = f1 + 0.5;\n"
975 "}\n"
976 "#endif\n"
977 "#else // !MODE_WATER\n"
978 "\n"
979 "\n"
980 "\n"
981 "\n"
982 "// common definitions between vertex shader and fragment shader:\n"
983 "\n"
984 "varying vec2 TexCoord;\n"
985 "#ifdef USEVERTEXTEXTUREBLEND\n"
986 "varying vec2 TexCoord2;\n"
987 "#endif\n"
988 "#ifdef USELIGHTMAP\n"
989 "varying vec2 TexCoordLightmap;\n"
990 "#endif\n"
991 "\n"
992 "#ifdef MODE_LIGHTSOURCE\n"
993 "varying vec3 CubeVector;\n"
994 "#endif\n"
995 "\n"
996 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
997 "varying vec3 LightVector;\n"
998 "#endif\n"
999 "\n"
1000 "#ifdef USEEYEVECTOR\n"
1001 "varying vec3 EyeVector;\n"
1002 "#endif\n"
1003 "#ifdef USEFOG\n"
1004 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1005 "#endif\n"
1006 "\n"
1007 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1008 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1009 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1010 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1011 "#endif\n"
1012 "\n"
1013 "#ifdef USEREFLECTION\n"
1014 "varying vec4 ModelViewProjectionPosition;\n"
1015 "#endif\n"
1016 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1017 "uniform vec3 LightPosition;\n"
1018 "varying vec4 ModelViewPosition;\n"
1019 "#endif\n"
1020 "\n"
1021 "#ifdef MODE_LIGHTSOURCE\n"
1022 "uniform vec3 LightPosition;\n"
1023 "#endif\n"
1024 "uniform vec3 EyePosition;\n"
1025 "#ifdef MODE_LIGHTDIRECTION\n"
1026 "uniform vec3 LightDir;\n"
1027 "#endif\n"
1028 "uniform vec4 FogPlane;\n"
1029 "\n"
1030 "#ifdef USESHADOWMAPORTHO\n"
1031 "varying vec3 ShadowMapTC;\n"
1032 "#endif\n"
1033 "\n"
1034 "\n"
1035 "\n"
1036 "\n"
1037 "\n"
1038 "// 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"
1039 "\n"
1040 "// fragment shader specific:\n"
1041 "#ifdef FRAGMENT_SHADER\n"
1042 "\n"
1043 "uniform sampler2D Texture_Normal;\n"
1044 "uniform sampler2D Texture_Color;\n"
1045 "uniform sampler2D Texture_Gloss;\n"
1046 "#ifdef USEGLOW\n"
1047 "uniform sampler2D Texture_Glow;\n"
1048 "#endif\n"
1049 "#ifdef USEVERTEXTEXTUREBLEND\n"
1050 "uniform sampler2D Texture_SecondaryNormal;\n"
1051 "uniform sampler2D Texture_SecondaryColor;\n"
1052 "uniform sampler2D Texture_SecondaryGloss;\n"
1053 "#ifdef USEGLOW\n"
1054 "uniform sampler2D Texture_SecondaryGlow;\n"
1055 "#endif\n"
1056 "#endif\n"
1057 "#ifdef USECOLORMAPPING\n"
1058 "uniform sampler2D Texture_Pants;\n"
1059 "uniform sampler2D Texture_Shirt;\n"
1060 "#endif\n"
1061 "#ifdef USEFOG\n"
1062 "#ifdef USEFOGHEIGHTTEXTURE\n"
1063 "uniform sampler2D Texture_FogHeightTexture;\n"
1064 "#endif\n"
1065 "uniform sampler2D Texture_FogMask;\n"
1066 "#endif\n"
1067 "#ifdef USELIGHTMAP\n"
1068 "uniform sampler2D Texture_Lightmap;\n"
1069 "#endif\n"
1070 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1071 "uniform sampler2D Texture_Deluxemap;\n"
1072 "#endif\n"
1073 "#ifdef USEREFLECTION\n"
1074 "uniform sampler2D Texture_Reflection;\n"
1075 "#endif\n"
1076 "\n"
1077 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1078 "uniform sampler2D Texture_ScreenDepth;\n"
1079 "uniform sampler2D Texture_ScreenNormalMap;\n"
1080 "#endif\n"
1081 "#ifdef USEDEFERREDLIGHTMAP\n"
1082 "uniform sampler2D Texture_ScreenDiffuse;\n"
1083 "uniform sampler2D Texture_ScreenSpecular;\n"
1084 "#endif\n"
1085 "\n"
1086 "uniform myhalf3 Color_Pants;\n"
1087 "uniform myhalf3 Color_Shirt;\n"
1088 "uniform myhalf3 FogColor;\n"
1089 "\n"
1090 "#ifdef USEFOG\n"
1091 "uniform float FogRangeRecip;\n"
1092 "uniform float FogPlaneViewDist;\n"
1093 "uniform float FogHeightFade;\n"
1094 "vec3 FogVertex(vec3 surfacecolor)\n"
1095 "{\n"
1096 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1097 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1098 "       float fogfrac;\n"
1099 "#ifdef USEFOGHEIGHTTEXTURE\n"
1100 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1101 "       fogfrac = fogheightpixel.a;\n"
1102 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1103 "#else\n"
1104 "# ifdef USEFOGOUTSIDE\n"
1105 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1106 "# else\n"
1107 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1108 "# endif\n"
1109 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1110 "#endif\n"
1111 "}\n"
1112 "#endif\n"
1113 "\n"
1114 "#ifdef USEOFFSETMAPPING\n"
1115 "uniform float OffsetMapping_Scale;\n"
1116 "vec2 OffsetMapping(vec2 TexCoord)\n"
1117 "{\n"
1118 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1119 "       // 14 sample relief mapping: linear search and then binary search\n"
1120 "       // this basically steps forward a small amount repeatedly until it finds\n"
1121 "       // itself inside solid, then jitters forward and back using decreasing\n"
1122 "       // amounts to find the impact\n"
1123 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1124 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1125 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1126 "       vec3 RT = vec3(TexCoord, 1);\n"
1127 "       OffsetVector *= 0.1;\n"
1128 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1129 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1130 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1131 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1132 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1133 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1134 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1135 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1136 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1137 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1138 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1139 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1140 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1141 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1142 "       return RT.xy;\n"
1143 "#else\n"
1144 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1145 "       // this basically moves forward the full distance, and then backs up based\n"
1146 "       // on height of samples\n"
1147 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1148 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1149 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1150 "       TexCoord += OffsetVector;\n"
1151 "       OffsetVector *= 0.333;\n"
1152 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1153 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1154 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1155 "       return TexCoord;\n"
1156 "#endif\n"
1157 "}\n"
1158 "#endif // USEOFFSETMAPPING\n"
1159 "\n"
1160 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1161 "uniform sampler2D Texture_Attenuation;\n"
1162 "uniform samplerCube Texture_Cube;\n"
1163 "#endif\n"
1164 "\n"
1165 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1166 "\n"
1167 "#ifdef USESHADOWMAP2D\n"
1168 "# ifdef USESHADOWSAMPLER\n"
1169 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1170 "# else\n"
1171 "uniform sampler2D Texture_ShadowMap2D;\n"
1172 "# endif\n"
1173 "#endif\n"
1174 "\n"
1175 "#ifdef USESHADOWMAPVSDCT\n"
1176 "uniform samplerCube Texture_CubeProjection;\n"
1177 "#endif\n"
1178 "\n"
1179 "#if defined(USESHADOWMAP2D)\n"
1180 "uniform vec2 ShadowMap_TextureScale;\n"
1181 "uniform vec4 ShadowMap_Parameters;\n"
1182 "#endif\n"
1183 "\n"
1184 "#if defined(USESHADOWMAP2D)\n"
1185 "# ifdef USESHADOWMAPORTHO\n"
1186 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1187 "# else\n"
1188 "#  ifdef USESHADOWMAPVSDCT\n"
1189 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1190 "{\n"
1191 "       vec3 adir = abs(dir);\n"
1192 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1193 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1194 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1195 "}\n"
1196 "#  else\n"
1197 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1198 "{\n"
1199 "       vec3 adir = abs(dir);\n"
1200 "       float ma = adir.z;\n"
1201 "       vec4 proj = vec4(dir, 2.5);\n"
1202 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1203 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1204 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1205 "       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"
1206 "}\n"
1207 "#  endif\n"
1208 "# endif\n"
1209 "#endif // defined(USESHADOWMAP2D)\n"
1210 "\n"
1211 "# ifdef USESHADOWMAP2D\n"
1212 "float ShadowMapCompare(vec3 dir)\n"
1213 "{\n"
1214 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1215 "       float f;\n"
1216 "\n"
1217 "#  ifdef USESHADOWSAMPLER\n"
1218 "#    ifdef USESHADOWMAPPCF\n"
1219 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1220 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1221 "       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"
1222 "#    else\n"
1223 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1224 "#    endif\n"
1225 "#  else\n"
1226 "#    ifdef USESHADOWMAPPCF\n"
1227 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1228 "#      ifdef GL_ARB_texture_gather\n"
1229 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1230 "#      else\n"
1231 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1232 "#      endif\n"
1233 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1234 "#      if USESHADOWMAPPCF > 1\n"
1235 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1236 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1237 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1238 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1239 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1240 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1241 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1242 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1243 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1244 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1245 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1246 "       locols.yz += group2.ab;\n"
1247 "       hicols.yz += group8.rg;\n"
1248 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1249 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1250 "                               mix(locols, hicols, offset.y);\n"
1251 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1252 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1253 "       f = dot(cols, vec4(1.0/25.0));\n"
1254 "#      else\n"
1255 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1256 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1257 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1258 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1259 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1260 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1261 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1262 "#      endif\n"
1263 "#     else\n"
1264 "#      ifdef GL_EXT_gpu_shader4\n"
1265 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1266 "#      else\n"
1267 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1268 "#      endif\n"
1269 "#      if USESHADOWMAPPCF > 1\n"
1270 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1271 "       center *= ShadowMap_TextureScale;\n"
1272 "       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"
1273 "       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"
1274 "       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"
1275 "       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"
1276 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1277 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1278 "#      else\n"
1279 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1280 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1281 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1282 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1283 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1284 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1285 "#      endif\n"
1286 "#     endif\n"
1287 "#    else\n"
1288 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1289 "#    endif\n"
1290 "#  endif\n"
1291 "#  ifdef USESHADOWMAPORTHO\n"
1292 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1293 "#  else\n"
1294 "       return f;\n"
1295 "#  endif\n"
1296 "}\n"
1297 "# endif\n"
1298 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1299 "#endif // FRAGMENT_SHADER\n"
1300 "\n"
1301 "\n"
1302 "\n"
1303 "\n"
1304 "#ifdef MODE_DEFERREDGEOMETRY\n"
1305 "#ifdef VERTEX_SHADER\n"
1306 "uniform mat4 TexMatrix;\n"
1307 "#ifdef USEVERTEXTEXTUREBLEND\n"
1308 "uniform mat4 BackgroundTexMatrix;\n"
1309 "#endif\n"
1310 "uniform mat4 ModelViewMatrix;\n"
1311 "void main(void)\n"
1312 "{\n"
1313 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1314 "#ifdef USEVERTEXTEXTUREBLEND\n"
1315 "       gl_FrontColor = gl_Color;\n"
1316 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1317 "#endif\n"
1318 "\n"
1319 "       // transform unnormalized eye direction into tangent space\n"
1320 "#ifdef USEOFFSETMAPPING\n"
1321 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1322 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1323 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1324 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1325 "#endif\n"
1326 "\n"
1327 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1328 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1329 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1330 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1331 "}\n"
1332 "#endif // VERTEX_SHADER\n"
1333 "\n"
1334 "#ifdef FRAGMENT_SHADER\n"
1335 "void main(void)\n"
1336 "{\n"
1337 "#ifdef USEOFFSETMAPPING\n"
1338 "       // apply offsetmapping\n"
1339 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1340 "#define TexCoord TexCoordOffset\n"
1341 "#endif\n"
1342 "\n"
1343 "#ifdef USEALPHAKILL\n"
1344 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1345 "               discard;\n"
1346 "#endif\n"
1347 "\n"
1348 "#ifdef USEVERTEXTEXTUREBLEND\n"
1349 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1350 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1351 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1352 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1353 "#endif\n"
1354 "\n"
1355 "#ifdef USEVERTEXTEXTUREBLEND\n"
1356 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1357 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1358 "#else\n"
1359 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1360 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1361 "#endif\n"
1362 "\n"
1363 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1364 "}\n"
1365 "#endif // FRAGMENT_SHADER\n"
1366 "#else // !MODE_DEFERREDGEOMETRY\n"
1367 "\n"
1368 "\n"
1369 "\n"
1370 "\n"
1371 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1372 "#ifdef VERTEX_SHADER\n"
1373 "uniform mat4 ModelViewMatrix;\n"
1374 "void main(void)\n"
1375 "{\n"
1376 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1377 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1378 "}\n"
1379 "#endif // VERTEX_SHADER\n"
1380 "\n"
1381 "#ifdef FRAGMENT_SHADER\n"
1382 "uniform mat4 ViewToLight;\n"
1383 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1384 "uniform vec2 ScreenToDepth;\n"
1385 "uniform myhalf3 DeferredColor_Ambient;\n"
1386 "uniform myhalf3 DeferredColor_Diffuse;\n"
1387 "#ifdef USESPECULAR\n"
1388 "uniform myhalf3 DeferredColor_Specular;\n"
1389 "uniform myhalf SpecularPower;\n"
1390 "#endif\n"
1391 "uniform myhalf2 PixelToScreenTexCoord;\n"
1392 "void main(void)\n"
1393 "{\n"
1394 "       // calculate viewspace pixel position\n"
1395 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1396 "       vec3 position;\n"
1397 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1398 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1399 "       // decode viewspace pixel normal\n"
1400 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1401 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1402 "       // surfacenormal = pixel normal in viewspace\n"
1403 "       // LightVector = pixel to light in viewspace\n"
1404 "       // CubeVector = position in lightspace\n"
1405 "       // eyevector = pixel to view in viewspace\n"
1406 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1407 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1408 "#ifdef USEDIFFUSE\n"
1409 "       // calculate diffuse shading\n"
1410 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1411 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1412 "#endif\n"
1413 "#ifdef USESPECULAR\n"
1414 "       // calculate directional shading\n"
1415 "       vec3 eyevector = position * -1.0;\n"
1416 "#  ifdef USEEXACTSPECULARMATH\n"
1417 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1418 "#  else\n"
1419 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1420 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1421 "#  endif\n"
1422 "#endif\n"
1423 "\n"
1424 "#if defined(USESHADOWMAP2D)\n"
1425 "       fade *= ShadowMapCompare(CubeVector);\n"
1426 "#endif\n"
1427 "\n"
1428 "#ifdef USEDIFFUSE\n"
1429 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1430 "#else\n"
1431 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1432 "#endif\n"
1433 "#ifdef USESPECULAR\n"
1434 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1435 "#else\n"
1436 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1437 "#endif\n"
1438 "\n"
1439 "# ifdef USECUBEFILTER\n"
1440 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1441 "       gl_FragData[0].rgb *= cubecolor;\n"
1442 "       gl_FragData[1].rgb *= cubecolor;\n"
1443 "# endif\n"
1444 "}\n"
1445 "#endif // FRAGMENT_SHADER\n"
1446 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1447 "\n"
1448 "\n"
1449 "\n"
1450 "\n"
1451 "#ifdef VERTEX_SHADER\n"
1452 "uniform mat4 TexMatrix;\n"
1453 "#ifdef USEVERTEXTEXTUREBLEND\n"
1454 "uniform mat4 BackgroundTexMatrix;\n"
1455 "#endif\n"
1456 "#ifdef MODE_LIGHTSOURCE\n"
1457 "uniform mat4 ModelToLight;\n"
1458 "#endif\n"
1459 "#ifdef USESHADOWMAPORTHO\n"
1460 "uniform mat4 ShadowMapMatrix;\n"
1461 "#endif\n"
1462 "void main(void)\n"
1463 "{\n"
1464 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1465 "       gl_FrontColor = gl_Color;\n"
1466 "#endif\n"
1467 "       // copy the surface texcoord\n"
1468 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1469 "#ifdef USEVERTEXTEXTUREBLEND\n"
1470 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1471 "#endif\n"
1472 "#ifdef USELIGHTMAP\n"
1473 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1474 "#endif\n"
1475 "\n"
1476 "#ifdef MODE_LIGHTSOURCE\n"
1477 "       // transform vertex position into light attenuation/cubemap space\n"
1478 "       // (-1 to +1 across the light box)\n"
1479 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1480 "\n"
1481 "# ifdef USEDIFFUSE\n"
1482 "       // transform unnormalized light direction into tangent space\n"
1483 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1484 "       //  normalize it per pixel)\n"
1485 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1486 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1487 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1488 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1489 "# endif\n"
1490 "#endif\n"
1491 "\n"
1492 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1493 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1494 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1495 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1496 "#endif\n"
1497 "\n"
1498 "       // transform unnormalized eye direction into tangent space\n"
1499 "#ifdef USEEYEVECTOR\n"
1500 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1501 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1502 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1503 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1504 "#endif\n"
1505 "\n"
1506 "#ifdef USEFOG\n"
1507 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1508 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1509 "#endif\n"
1510 "\n"
1511 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1512 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1513 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1514 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1515 "#endif\n"
1516 "\n"
1517 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1518 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1519 "\n"
1520 "#ifdef USESHADOWMAPORTHO\n"
1521 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1522 "#endif\n"
1523 "\n"
1524 "#ifdef USEREFLECTION\n"
1525 "       ModelViewProjectionPosition = gl_Position;\n"
1526 "#endif\n"
1527 "}\n"
1528 "#endif // VERTEX_SHADER\n"
1529 "\n"
1530 "\n"
1531 "\n"
1532 "\n"
1533 "#ifdef FRAGMENT_SHADER\n"
1534 "#ifdef USEDEFERREDLIGHTMAP\n"
1535 "uniform myhalf2 PixelToScreenTexCoord;\n"
1536 "uniform myhalf3 DeferredMod_Diffuse;\n"
1537 "uniform myhalf3 DeferredMod_Specular;\n"
1538 "#endif\n"
1539 "uniform myhalf3 Color_Ambient;\n"
1540 "uniform myhalf3 Color_Diffuse;\n"
1541 "uniform myhalf3 Color_Specular;\n"
1542 "uniform myhalf SpecularPower;\n"
1543 "#ifdef USEGLOW\n"
1544 "uniform myhalf3 Color_Glow;\n"
1545 "#endif\n"
1546 "uniform myhalf Alpha;\n"
1547 "#ifdef USEREFLECTION\n"
1548 "uniform vec4 DistortScaleRefractReflect;\n"
1549 "uniform vec4 ScreenScaleRefractReflect;\n"
1550 "uniform vec4 ScreenCenterRefractReflect;\n"
1551 "uniform myhalf4 ReflectColor;\n"
1552 "#endif\n"
1553 "#ifdef USEREFLECTCUBE\n"
1554 "uniform mat4 ModelToReflectCube;\n"
1555 "uniform sampler2D Texture_ReflectMask;\n"
1556 "uniform samplerCube Texture_ReflectCube;\n"
1557 "#endif\n"
1558 "#ifdef MODE_LIGHTDIRECTION\n"
1559 "uniform myhalf3 LightColor;\n"
1560 "#endif\n"
1561 "#ifdef MODE_LIGHTSOURCE\n"
1562 "uniform myhalf3 LightColor;\n"
1563 "#endif\n"
1564 "void main(void)\n"
1565 "{\n"
1566 "#ifdef USEOFFSETMAPPING\n"
1567 "       // apply offsetmapping\n"
1568 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1569 "#define TexCoord TexCoordOffset\n"
1570 "#endif\n"
1571 "\n"
1572 "       // combine the diffuse textures (base, pants, shirt)\n"
1573 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1574 "#ifdef USEALPHAKILL\n"
1575 "       if (color.a < 0.5)\n"
1576 "               discard;\n"
1577 "#endif\n"
1578 "       color.a *= Alpha;\n"
1579 "#ifdef USECOLORMAPPING\n"
1580 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1581 "#endif\n"
1582 "#ifdef USEVERTEXTEXTUREBLEND\n"
1583 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1584 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1585 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1586 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1587 "       color.a = 1.0;\n"
1588 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1589 "#endif\n"
1590 "\n"
1591 "       // get the surface normal\n"
1592 "#ifdef USEVERTEXTEXTUREBLEND\n"
1593 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1594 "#else\n"
1595 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1596 "#endif\n"
1597 "\n"
1598 "       // get the material colors\n"
1599 "       myhalf3 diffusetex = color.rgb;\n"
1600 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1601 "# ifdef USEVERTEXTEXTUREBLEND\n"
1602 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1603 "# else\n"
1604 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1605 "# endif\n"
1606 "#endif\n"
1607 "\n"
1608 "#ifdef USEREFLECTCUBE\n"
1609 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1610 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1611 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1612 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1613 "#endif\n"
1614 "\n"
1615 "\n"
1616 "\n"
1617 "\n"
1618 "#ifdef MODE_LIGHTSOURCE\n"
1619 "       // light source\n"
1620 "#ifdef USEDIFFUSE\n"
1621 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1622 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1623 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1624 "#ifdef USESPECULAR\n"
1625 "#ifdef USEEXACTSPECULARMATH\n"
1626 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1627 "#else\n"
1628 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1629 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1630 "#endif\n"
1631 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1632 "#endif\n"
1633 "#else\n"
1634 "       color.rgb = diffusetex * Color_Ambient;\n"
1635 "#endif\n"
1636 "       color.rgb *= LightColor;\n"
1637 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1638 "#if defined(USESHADOWMAP2D)\n"
1639 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1640 "#endif\n"
1641 "# ifdef USECUBEFILTER\n"
1642 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1643 "# endif\n"
1644 "#endif // MODE_LIGHTSOURCE\n"
1645 "\n"
1646 "\n"
1647 "\n"
1648 "\n"
1649 "#ifdef MODE_LIGHTDIRECTION\n"
1650 "#define SHADING\n"
1651 "#ifdef USEDIFFUSE\n"
1652 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1653 "#endif\n"
1654 "#define lightcolor LightColor\n"
1655 "#endif // MODE_LIGHTDIRECTION\n"
1656 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1657 "#define SHADING\n"
1658 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1659 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1660 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1661 "       // convert modelspace light vector to tangentspace\n"
1662 "       myhalf3 lightnormal;\n"
1663 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1664 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1665 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1666 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1667 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1668 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1669 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1670 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1671 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1672 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1673 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1674 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1675 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1676 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1677 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1678 "#define SHADING\n"
1679 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1680 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1681 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1682 "#endif\n"
1683 "\n"
1684 "\n"
1685 "\n"
1686 "\n"
1687 "#ifdef MODE_FAKELIGHT\n"
1688 "#define SHADING\n"
1689 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1690 "myhalf3 lightcolor = myhalf3(1.0);\n"
1691 "#endif // MODE_FAKELIGHT\n"
1692 "\n"
1693 "\n"
1694 "\n"
1695 "\n"
1696 "#ifdef MODE_LIGHTMAP\n"
1697 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1698 "#endif // MODE_LIGHTMAP\n"
1699 "#ifdef MODE_VERTEXCOLOR\n"
1700 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1701 "#endif // MODE_VERTEXCOLOR\n"
1702 "#ifdef MODE_FLATCOLOR\n"
1703 "       color.rgb = diffusetex * Color_Ambient;\n"
1704 "#endif // MODE_FLATCOLOR\n"
1705 "\n"
1706 "\n"
1707 "\n"
1708 "\n"
1709 "#ifdef SHADING\n"
1710 "# ifdef USEDIFFUSE\n"
1711 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1712 "#  ifdef USESPECULAR\n"
1713 "#   ifdef USEEXACTSPECULARMATH\n"
1714 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1715 "#   else\n"
1716 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1717 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1718 "#   endif\n"
1719 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1720 "#  else\n"
1721 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1722 "#  endif\n"
1723 "# else\n"
1724 "       color.rgb = diffusetex * Color_Ambient;\n"
1725 "# endif\n"
1726 "#endif\n"
1727 "\n"
1728 "#ifdef USESHADOWMAPORTHO\n"
1729 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1730 "#endif\n"
1731 "\n"
1732 "#ifdef USEDEFERREDLIGHTMAP\n"
1733 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1734 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1735 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1736 "#endif\n"
1737 "\n"
1738 "#ifdef USEGLOW\n"
1739 "#ifdef USEVERTEXTEXTUREBLEND\n"
1740 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1741 "#else\n"
1742 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1743 "#endif\n"
1744 "#endif\n"
1745 "\n"
1746 "#ifdef USEFOG\n"
1747 "       color.rgb = FogVertex(color.rgb);\n"
1748 "#endif\n"
1749 "\n"
1750 "       // 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"
1751 "#ifdef USEREFLECTION\n"
1752 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1753 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1754 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1755 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1756 "       // FIXME temporary hack to detect the case that the reflection\n"
1757 "       // gets blackened at edges due to leaving the area that contains actual\n"
1758 "       // content.\n"
1759 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1760 "       // 'appening.\n"
1761 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1762 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1763 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1764 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1765 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1766 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1767 "#endif\n"
1768 "\n"
1769 "       gl_FragColor = vec4(color);\n"
1770 "}\n"
1771 "#endif // FRAGMENT_SHADER\n"
1772 "\n"
1773 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1774 "#endif // !MODE_DEFERREDGEOMETRY\n"
1775 "#endif // !MODE_WATER\n"
1776 "#endif // !MODE_REFRACTION\n"
1777 "#endif // !MODE_BLOOMBLUR\n"
1778 "#endif // !MODE_GENERIC\n"
1779 "#endif // !MODE_POSTPROCESS\n"
1780 "#endif // !MODE_SHOWDEPTH\n"
1781 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1782 ;
1783
1784 /*
1785 =========================================================================================================================================================
1786
1787
1788
1789 =========================================================================================================================================================
1790
1791
1792
1793 =========================================================================================================================================================
1794
1795
1796
1797 =========================================================================================================================================================
1798
1799
1800
1801 =========================================================================================================================================================
1802
1803
1804
1805 =========================================================================================================================================================
1806
1807
1808
1809 =========================================================================================================================================================
1810 */
1811
1812 const char *builtincgshaderstring =
1813 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1814 "// written by Forest 'LordHavoc' Hale\n"
1815 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1816 "\n"
1817 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1818 "#if defined(USEREFLECTION)\n"
1819 "#undef USESHADOWMAPORTHO\n"
1820 "#endif\n"
1821 "\n"
1822 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1823 "# define USEFOG\n"
1824 "#endif\n"
1825 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1826 "#define USELIGHTMAP\n"
1827 "#endif\n"
1828 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1829 "#define USEEYEVECTOR\n"
1830 "#endif\n"
1831 "\n"
1832 "#ifdef FRAGMENT_SHADER\n"
1833 "#ifdef HLSL\n"
1834 "//#undef USESHADOWMAPPCF\n"
1835 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1836 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1837 "#else\n"
1838 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1839 "#endif\n"
1840 "#endif\n"
1841 "\n"
1842 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1843 "#ifdef VERTEX_SHADER\n"
1844 "void main\n"
1845 "(\n"
1846 "float4 gl_Vertex : POSITION,\n"
1847 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1848 "out float4 gl_Position : POSITION,\n"
1849 "out float Depth : TEXCOORD0\n"
1850 ")\n"
1851 "{\n"
1852 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1853 "       Depth = gl_Position.z;\n"
1854 "}\n"
1855 "#endif\n"
1856 "\n"
1857 "#ifdef FRAGMENT_SHADER\n"
1858 "void main\n"
1859 "(\n"
1860 "float Depth : TEXCOORD0,\n"
1861 "out float4 gl_FragColor : COLOR\n"
1862 ")\n"
1863 "{\n"
1864 "//     float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1865 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1866 "       temp.yz -= floor(temp.yz);\n"
1867 "       gl_FragColor = temp;\n"
1868 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1869 "}\n"
1870 "#endif\n"
1871 "#else // !MODE_DEPTH_ORSHADOW\n"
1872 "\n"
1873 "\n"
1874 "\n"
1875 "\n"
1876 "#ifdef MODE_SHOWDEPTH\n"
1877 "#ifdef VERTEX_SHADER\n"
1878 "void main\n"
1879 "(\n"
1880 "float4 gl_Vertex : POSITION,\n"
1881 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1882 "out float4 gl_Position : POSITION,\n"
1883 "out float4 gl_FrontColor : COLOR0\n"
1884 ")\n"
1885 "{\n"
1886 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1887 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1888 "}\n"
1889 "#endif\n"
1890 "\n"
1891 "#ifdef FRAGMENT_SHADER\n"
1892 "void main\n"
1893 "(\n"
1894 "float4 gl_FrontColor : COLOR0,\n"
1895 "out float4 gl_FragColor : COLOR\n"
1896 ")\n"
1897 "{\n"
1898 "       gl_FragColor = gl_FrontColor;\n"
1899 "}\n"
1900 "#endif\n"
1901 "#else // !MODE_SHOWDEPTH\n"
1902 "\n"
1903 "\n"
1904 "\n"
1905 "\n"
1906 "#ifdef MODE_POSTPROCESS\n"
1907 "\n"
1908 "#ifdef VERTEX_SHADER\n"
1909 "void main\n"
1910 "(\n"
1911 "float4 gl_Vertex : POSITION,\n"
1912 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1913 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1914 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1915 "out float4 gl_Position : POSITION,\n"
1916 "out float2 TexCoord1 : TEXCOORD0,\n"
1917 "out float2 TexCoord2 : TEXCOORD1\n"
1918 ")\n"
1919 "{\n"
1920 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1921 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1922 "#ifdef USEBLOOM\n"
1923 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1924 "#endif\n"
1925 "}\n"
1926 "#endif\n"
1927 "\n"
1928 "#ifdef FRAGMENT_SHADER\n"
1929 "void main\n"
1930 "(\n"
1931 "float2 TexCoord1 : TEXCOORD0,\n"
1932 "float2 TexCoord2 : TEXCOORD1,\n"
1933 "uniform sampler Texture_First : register(s0),\n"
1934 "#ifdef USEBLOOM\n"
1935 "uniform sampler Texture_Second : register(s1),\n"
1936 "#endif\n"
1937 "#ifdef USEGAMMARAMPS\n"
1938 "uniform sampler Texture_GammaRamps : register(s2),\n"
1939 "#endif\n"
1940 "#ifdef USESATURATION\n"
1941 "uniform float Saturation : register(c30),\n"
1942 "#endif\n"
1943 "#ifdef USEVIEWTINT\n"
1944 "uniform float4 ViewTintColor : register(c41),\n"
1945 "#endif\n"
1946 "uniform float4 UserVec1 : register(c37),\n"
1947 "uniform float4 UserVec2 : register(c38),\n"
1948 "uniform float4 UserVec3 : register(c39),\n"
1949 "uniform float4 UserVec4 : register(c40),\n"
1950 "uniform float ClientTime : register(c2),\n"
1951 "uniform float2 PixelSize : register(c25),\n"
1952 "uniform float4 BloomColorSubtract : register(c43),\n"
1953 "out float4 gl_FragColor : COLOR\n"
1954 ")\n"
1955 "{\n"
1956 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1957 "#ifdef USEBLOOM\n"
1958 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1959 "#endif\n"
1960 "#ifdef USEVIEWTINT\n"
1961 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1962 "#endif\n"
1963 "\n"
1964 "#ifdef USEPOSTPROCESSING\n"
1965 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1966 "// 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"
1967 "       float sobel = 1.0;\n"
1968 "       // float2 ts = textureSize(Texture_First, 0);\n"
1969 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1970 "       float2 px = PixelSize;\n"
1971 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1972 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1973 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1974 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1975 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1976 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1977 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1978 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1979 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1980 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1981 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1982 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1983 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1984 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1985 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1986 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1987 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1988 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1989 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1990 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1991 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1992 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
1993 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
1994 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
1995 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
1996 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1997 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1998 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1999 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2000 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2001 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2002 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2003 "#endif\n"
2004 "\n"
2005 "#ifdef USESATURATION\n"
2006 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2007 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2008 "       // 'vampire sight' effect, wheres red is compensated\n"
2009 "       #ifdef SATURATION_REDCOMPENSATE\n"
2010 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2011 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2012 "               gl_FragColor.r += r;\n"
2013 "       #else\n"
2014 "               // normal desaturation\n"
2015 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2016 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2017 "       #endif\n"
2018 "#endif\n"
2019 "\n"
2020 "#ifdef USEGAMMARAMPS\n"
2021 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2022 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2023 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2024 "#endif\n"
2025 "}\n"
2026 "#endif\n"
2027 "#else // !MODE_POSTPROCESS\n"
2028 "\n"
2029 "\n"
2030 "\n"
2031 "\n"
2032 "#ifdef MODE_GENERIC\n"
2033 "#ifdef VERTEX_SHADER\n"
2034 "void main\n"
2035 "(\n"
2036 "float4 gl_Vertex : POSITION,\n"
2037 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2038 "float4 gl_Color : COLOR0,\n"
2039 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2040 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2041 "out float4 gl_Position : POSITION,\n"
2042 "#ifdef USEDIFFUSE\n"
2043 "out float2 TexCoord1 : TEXCOORD0,\n"
2044 "#endif\n"
2045 "#ifdef USESPECULAR\n"
2046 "out float2 TexCoord2 : TEXCOORD1,\n"
2047 "#endif\n"
2048 "out float4 gl_FrontColor : COLOR\n"
2049 ")\n"
2050 "{\n"
2051 "#ifdef HLSL\n"
2052 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2053 "#else\n"
2054 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2055 "#endif\n"
2056 "#ifdef USEDIFFUSE\n"
2057 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2058 "#endif\n"
2059 "#ifdef USESPECULAR\n"
2060 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2061 "#endif\n"
2062 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2063 "}\n"
2064 "#endif\n"
2065 "\n"
2066 "#ifdef FRAGMENT_SHADER\n"
2067 "\n"
2068 "void main\n"
2069 "(\n"
2070 "float4 gl_FrontColor : COLOR0,\n"
2071 "float2 TexCoord1 : TEXCOORD0,\n"
2072 "float2 TexCoord2 : TEXCOORD1,\n"
2073 "#ifdef USEDIFFUSE\n"
2074 "uniform sampler Texture_First : register(s0),\n"
2075 "#endif\n"
2076 "#ifdef USESPECULAR\n"
2077 "uniform sampler Texture_Second : register(s1),\n"
2078 "#endif\n"
2079 "out float4 gl_FragColor : COLOR\n"
2080 ")\n"
2081 "{\n"
2082 "       gl_FragColor = gl_FrontColor;\n"
2083 "#ifdef USEDIFFUSE\n"
2084 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2085 "#endif\n"
2086 "\n"
2087 "#ifdef USESPECULAR\n"
2088 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2089 "# ifdef USECOLORMAPPING\n"
2090 "       gl_FragColor *= tex2;\n"
2091 "# endif\n"
2092 "# ifdef USEGLOW\n"
2093 "       gl_FragColor += tex2;\n"
2094 "# endif\n"
2095 "# ifdef USEVERTEXTEXTUREBLEND\n"
2096 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2097 "# endif\n"
2098 "#endif\n"
2099 "}\n"
2100 "#endif\n"
2101 "#else // !MODE_GENERIC\n"
2102 "\n"
2103 "\n"
2104 "\n"
2105 "\n"
2106 "#ifdef MODE_BLOOMBLUR\n"
2107 "#ifdef VERTEX_SHADER\n"
2108 "void main\n"
2109 "(\n"
2110 "float4 gl_Vertex : POSITION,\n"
2111 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2112 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2113 "out float4 gl_Position : POSITION,\n"
2114 "out float2 TexCoord : TEXCOORD0\n"
2115 ")\n"
2116 "{\n"
2117 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2118 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2119 "}\n"
2120 "#endif\n"
2121 "\n"
2122 "#ifdef FRAGMENT_SHADER\n"
2123 "\n"
2124 "void main\n"
2125 "(\n"
2126 "float2 TexCoord : TEXCOORD0,\n"
2127 "uniform sampler Texture_First : register(s0),\n"
2128 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2129 "out float4 gl_FragColor : COLOR\n"
2130 ")\n"
2131 "{\n"
2132 "       int i;\n"
2133 "       float2 tc = TexCoord;\n"
2134 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2135 "       tc += BloomBlur_Parameters.xy;\n"
2136 "       for (i = 1;i < SAMPLES;i++)\n"
2137 "       {\n"
2138 "               color += tex2D(Texture_First, tc).rgb;\n"
2139 "               tc += BloomBlur_Parameters.xy;\n"
2140 "       }\n"
2141 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2142 "}\n"
2143 "#endif\n"
2144 "#else // !MODE_BLOOMBLUR\n"
2145 "#ifdef MODE_REFRACTION\n"
2146 "#ifdef VERTEX_SHADER\n"
2147 "void main\n"
2148 "(\n"
2149 "float4 gl_Vertex : POSITION,\n"
2150 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2151 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2152 "uniform float4x4 TexMatrix : register(c0),\n"
2153 "uniform float3 EyePosition : register(c24),\n"
2154 "out float4 gl_Position : POSITION,\n"
2155 "out float2 TexCoord : TEXCOORD0,\n"
2156 "out float3 EyeVector : TEXCOORD1,\n"
2157 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2158 ")\n"
2159 "{\n"
2160 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2161 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2162 "       ModelViewProjectionPosition = gl_Position;\n"
2163 "}\n"
2164 "#endif\n"
2165 "\n"
2166 "#ifdef FRAGMENT_SHADER\n"
2167 "void main\n"
2168 "(\n"
2169 "float2 TexCoord : TEXCOORD0,\n"
2170 "float3 EyeVector : TEXCOORD1,\n"
2171 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2172 "uniform sampler Texture_Normal : register(s0),\n"
2173 "uniform sampler Texture_Refraction : register(s3),\n"
2174 "uniform sampler Texture_Reflection : register(s7),\n"
2175 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2176 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2177 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2178 "uniform float4 RefractColor : register(c29),\n"
2179 "out float4 gl_FragColor : COLOR\n"
2180 ")\n"
2181 "{\n"
2182 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2183 "       //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"
2184 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2185 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2186 "       // FIXME temporary hack to detect the case that the reflection\n"
2187 "       // gets blackened at edges due to leaving the area that contains actual\n"
2188 "       // content.\n"
2189 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2190 "       // 'appening.\n"
2191 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2192 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2193 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2194 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2195 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2196 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2197 "}\n"
2198 "#endif\n"
2199 "#else // !MODE_REFRACTION\n"
2200 "\n"
2201 "\n"
2202 "\n"
2203 "\n"
2204 "#ifdef MODE_WATER\n"
2205 "#ifdef VERTEX_SHADER\n"
2206 "\n"
2207 "void main\n"
2208 "(\n"
2209 "float4 gl_Vertex : POSITION,\n"
2210 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2211 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2212 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2213 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2214 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2215 "uniform float4x4 TexMatrix : register(c0),\n"
2216 "uniform float3 EyePosition : register(c24),\n"
2217 "out float4 gl_Position : POSITION,\n"
2218 "out float2 TexCoord : TEXCOORD0,\n"
2219 "out float3 EyeVector : TEXCOORD1,\n"
2220 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2221 ")\n"
2222 "{\n"
2223 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2224 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2225 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2226 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2227 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2228 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2229 "       ModelViewProjectionPosition = gl_Position;\n"
2230 "}\n"
2231 "#endif\n"
2232 "\n"
2233 "#ifdef FRAGMENT_SHADER\n"
2234 "void main\n"
2235 "(\n"
2236 "float2 TexCoord : TEXCOORD0,\n"
2237 "float3 EyeVector : TEXCOORD1,\n"
2238 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2239 "uniform sampler Texture_Normal : register(s0),\n"
2240 "uniform sampler Texture_Refraction : register(s3),\n"
2241 "uniform sampler Texture_Reflection : register(s7),\n"
2242 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2243 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2244 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2245 "uniform float4 RefractColor : register(c29),\n"
2246 "uniform float4 ReflectColor : register(c26),\n"
2247 "uniform float ReflectFactor : register(c27),\n"
2248 "uniform float ReflectOffset : register(c28),\n"
2249 "out float4 gl_FragColor : COLOR\n"
2250 ")\n"
2251 "{\n"
2252 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2253 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2254 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2255 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2256 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2257 "       // FIXME temporary hack to detect the case that the reflection\n"
2258 "       // gets blackened at edges due to leaving the area that contains actual\n"
2259 "       // content.\n"
2260 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2261 "       // 'appening.\n"
2262 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2263 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2264 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2265 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2266 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2267 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2268 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2269 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2270 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2271 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2272 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2273 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2274 "}\n"
2275 "#endif\n"
2276 "#else // !MODE_WATER\n"
2277 "\n"
2278 "\n"
2279 "\n"
2280 "\n"
2281 "// 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"
2282 "\n"
2283 "// fragment shader specific:\n"
2284 "#ifdef FRAGMENT_SHADER\n"
2285 "\n"
2286 "#ifdef USEFOG\n"
2287 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2288 "{\n"
2289 "       float fogfrac;\n"
2290 "#ifdef USEFOGHEIGHTTEXTURE\n"
2291 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2292 "       fogfrac = fogheightpixel.a;\n"
2293 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2294 "#else\n"
2295 "# ifdef USEFOGOUTSIDE\n"
2296 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2297 "# else\n"
2298 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2299 "# endif\n"
2300 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2301 "#endif\n"
2302 "}\n"
2303 "#endif\n"
2304 "\n"
2305 "#ifdef USEOFFSETMAPPING\n"
2306 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2307 "{\n"
2308 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2309 "       // 14 sample relief mapping: linear search and then binary search\n"
2310 "       // this basically steps forward a small amount repeatedly until it finds\n"
2311 "       // itself inside solid, then jitters forward and back using decreasing\n"
2312 "       // amounts to find the impact\n"
2313 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2314 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2315 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2316 "       float3 RT = float3(TexCoord, 1);\n"
2317 "       OffsetVector *= 0.1;\n"
2318 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2319 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2320 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2321 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2322 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2323 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2324 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2325 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2326 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2327 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2328 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2329 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2330 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2331 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2332 "       return RT.xy;\n"
2333 "#else\n"
2334 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2335 "       // this basically moves forward the full distance, and then backs up based\n"
2336 "       // on height of samples\n"
2337 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2338 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2339 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2340 "       TexCoord += OffsetVector;\n"
2341 "       OffsetVector *= 0.333;\n"
2342 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2343 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2344 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2345 "       return TexCoord;\n"
2346 "#endif\n"
2347 "}\n"
2348 "#endif // USEOFFSETMAPPING\n"
2349 "\n"
2350 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2351 "#if defined(USESHADOWMAP2D)\n"
2352 "# ifdef USESHADOWMAPORTHO\n"
2353 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2354 "# else\n"
2355 "#  ifdef USESHADOWMAPVSDCT\n"
2356 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2357 "{\n"
2358 "       float3 adir = abs(dir);\n"
2359 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2360 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2361 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2362 "}\n"
2363 "#  else\n"
2364 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2365 "{\n"
2366 "       float3 adir = abs(dir);\n"
2367 "       float ma = adir.z;\n"
2368 "       float4 proj = float4(dir, 2.5);\n"
2369 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2370 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2371 "#ifdef HLSL\n"
2372 "       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"
2373 "#else\n"
2374 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2375 "       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"
2376 "#endif\n"
2377 "}\n"
2378 "#  endif\n"
2379 "# endif\n"
2380 "#endif // defined(USESHADOWMAP2D)\n"
2381 "\n"
2382 "# ifdef USESHADOWMAP2D\n"
2383 "#ifdef USESHADOWMAPVSDCT\n"
2384 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2385 "#else\n"
2386 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2387 "#endif\n"
2388 "{\n"
2389 "#ifdef USESHADOWMAPVSDCT\n"
2390 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2391 "#else\n"
2392 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2393 "#endif\n"
2394 "       float f;\n"
2395 "\n"
2396 "#  ifdef USESHADOWSAMPLER\n"
2397 "#    ifdef USESHADOWMAPPCF\n"
2398 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2399 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2400 "       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"
2401 "#    else\n"
2402 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2403 "#    endif\n"
2404 "#  else\n"
2405 "#    ifdef USESHADOWMAPPCF\n"
2406 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2407 "#      ifdef GL_ARB_texture_gather\n"
2408 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2409 "#      else\n"
2410 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2411 "#      endif\n"
2412 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2413 "#      if USESHADOWMAPPCF > 1\n"
2414 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2415 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2416 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2417 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2418 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2419 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2420 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2421 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2422 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2423 "       float4 locols = float4(group1.ab, group3.ab);\n"
2424 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2425 "       locols.yz += group2.ab;\n"
2426 "       hicols.yz += group8.rg;\n"
2427 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2428 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2429 "                               lerp(locols, hicols, offset.y);\n"
2430 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2431 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2432 "       f = dot(cols, float4(1.0/25.0));\n"
2433 "#      else\n"
2434 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2435 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2436 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2437 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2438 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2439 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2440 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2441 "#      endif\n"
2442 "#     else\n"
2443 "#      ifdef GL_EXT_gpu_shader4\n"
2444 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2445 "#      else\n"
2446 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2447 "#      endif\n"
2448 "#      if USESHADOWMAPPCF > 1\n"
2449 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2450 "       center *= ShadowMap_TextureScale;\n"
2451 "       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"
2452 "       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"
2453 "       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"
2454 "       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"
2455 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2456 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2457 "#      else\n"
2458 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2459 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2460 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2461 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2462 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2463 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2464 "#      endif\n"
2465 "#     endif\n"
2466 "#    else\n"
2467 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2468 "#    endif\n"
2469 "#  endif\n"
2470 "#  ifdef USESHADOWMAPORTHO\n"
2471 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2472 "#  else\n"
2473 "       return f;\n"
2474 "#  endif\n"
2475 "}\n"
2476 "# endif\n"
2477 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2478 "#endif // FRAGMENT_SHADER\n"
2479 "\n"
2480 "\n"
2481 "\n"
2482 "\n"
2483 "#ifdef MODE_DEFERREDGEOMETRY\n"
2484 "#ifdef VERTEX_SHADER\n"
2485 "void main\n"
2486 "(\n"
2487 "float4 gl_Vertex : POSITION,\n"
2488 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2489 "#ifdef USEVERTEXTEXTUREBLEND\n"
2490 "float4 gl_Color : COLOR0,\n"
2491 "#endif\n"
2492 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2493 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2494 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2495 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2496 "uniform float4x4 TexMatrix : register(c0),\n"
2497 "#ifdef USEVERTEXTEXTUREBLEND\n"
2498 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2499 "#endif\n"
2500 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2501 "#ifdef USEOFFSETMAPPING\n"
2502 "uniform float3 EyePosition : register(c24),\n"
2503 "#endif\n"
2504 "out float4 gl_Position : POSITION,\n"
2505 "#ifdef USEVERTEXTEXTUREBLEND\n"
2506 "out float4 gl_FrontColor : COLOR,\n"
2507 "#endif\n"
2508 "out float4 TexCoordBoth : TEXCOORD0,\n"
2509 "#ifdef USEOFFSETMAPPING\n"
2510 "out float3 EyeVector : TEXCOORD2,\n"
2511 "#endif\n"
2512 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2513 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2514 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2515 ")\n"
2516 "{\n"
2517 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2518 "#ifdef USEVERTEXTEXTUREBLEND\n"
2519 "#ifdef HLSL\n"
2520 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2521 "#else\n"
2522 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2523 "#endif\n"
2524 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2525 "#endif\n"
2526 "\n"
2527 "       // transform unnormalized eye direction into tangent space\n"
2528 "#ifdef USEOFFSETMAPPING\n"
2529 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2530 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2531 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2532 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2533 "#endif\n"
2534 "\n"
2535 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2536 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2537 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2538 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2539 "       VectorR.w = gl_Position.z;\n"
2540 "}\n"
2541 "#endif // VERTEX_SHADER\n"
2542 "\n"
2543 "#ifdef FRAGMENT_SHADER\n"
2544 "void main\n"
2545 "(\n"
2546 "float4 TexCoordBoth : TEXCOORD0,\n"
2547 "float3 EyeVector : TEXCOORD2,\n"
2548 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2549 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2550 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2551 "uniform sampler Texture_Normal : register(s0),\n"
2552 "#ifdef USEALPHAKILL\n"
2553 "uniform sampler Texture_Color : register(s1),\n"
2554 "#endif\n"
2555 "uniform sampler Texture_Gloss : register(s2),\n"
2556 "#ifdef USEVERTEXTEXTUREBLEND\n"
2557 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2558 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2559 "#endif\n"
2560 "#ifdef USEOFFSETMAPPING\n"
2561 "uniform float OffsetMapping_Scale : register(c24),\n"
2562 "#endif\n"
2563 "uniform half SpecularPower : register(c36),\n"
2564 "#ifdef HLSL\n"
2565 "out float4 gl_FragData0 : COLOR0,\n"
2566 "out float4 gl_FragData1 : COLOR1\n"
2567 "#else\n"
2568 "out float4 gl_FragColor : COLOR\n"
2569 "#endif\n"
2570 ")\n"
2571 "{\n"
2572 "       float2 TexCoord = TexCoordBoth.xy;\n"
2573 "#ifdef USEOFFSETMAPPING\n"
2574 "       // apply offsetmapping\n"
2575 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2576 "#define TexCoord TexCoordOffset\n"
2577 "#endif\n"
2578 "\n"
2579 "#ifdef USEALPHAKILL\n"
2580 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2581 "               discard;\n"
2582 "#endif\n"
2583 "\n"
2584 "#ifdef USEVERTEXTEXTUREBLEND\n"
2585 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2586 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2587 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2588 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2589 "#endif\n"
2590 "\n"
2591 "#ifdef USEVERTEXTEXTUREBLEND\n"
2592 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2593 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2594 "#else\n"
2595 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2596 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2597 "#endif\n"
2598 "\n"
2599 "#ifdef HLSL\n"
2600 "       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"
2601 "       float Depth = VectorR.w / 256.0;\n"
2602 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2603 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2604 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2605 "       gl_FragData1 = depthcolor;\n"
2606 "#else\n"
2607 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2608 "#endif\n"
2609 "}\n"
2610 "#endif // FRAGMENT_SHADER\n"
2611 "#else // !MODE_DEFERREDGEOMETRY\n"
2612 "\n"
2613 "\n"
2614 "\n"
2615 "\n"
2616 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2617 "#ifdef VERTEX_SHADER\n"
2618 "void main\n"
2619 "(\n"
2620 "float4 gl_Vertex : POSITION,\n"
2621 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2622 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2623 "out float4 gl_Position : POSITION,\n"
2624 "out float4 ModelViewPosition : TEXCOORD0\n"
2625 ")\n"
2626 "{\n"
2627 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2628 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2629 "}\n"
2630 "#endif // VERTEX_SHADER\n"
2631 "\n"
2632 "#ifdef FRAGMENT_SHADER\n"
2633 "void main\n"
2634 "(\n"
2635 "#ifdef HLSL\n"
2636 "float2 Pixel : VPOS,\n"
2637 "#else\n"
2638 "float2 Pixel : WPOS,\n"
2639 "#endif\n"
2640 "float4 ModelViewPosition : TEXCOORD0,\n"
2641 "uniform float4x4 ViewToLight : register(c44),\n"
2642 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2643 "uniform float3 LightPosition : register(c23),\n"
2644 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2645 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2646 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2647 "#ifdef USESPECULAR\n"
2648 "uniform half3 DeferredColor_Specular : register(c11),\n"
2649 "uniform half SpecularPower : register(c36),\n"
2650 "#endif\n"
2651 "uniform sampler Texture_Attenuation : register(s9),\n"
2652 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2653 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2654 "\n"
2655 "#ifdef USECUBEFILTER\n"
2656 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2657 "#endif\n"
2658 "\n"
2659 "#ifdef USESHADOWMAP2D\n"
2660 "# ifdef USESHADOWSAMPLER\n"
2661 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2662 "# else\n"
2663 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2664 "# endif\n"
2665 "#endif\n"
2666 "\n"
2667 "#ifdef USESHADOWMAPVSDCT\n"
2668 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2669 "#endif\n"
2670 "\n"
2671 "#if defined(USESHADOWMAP2D)\n"
2672 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2673 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2674 "#endif\n"
2675 "\n"
2676 "out float4 gl_FragData0 : COLOR0,\n"
2677 "out float4 gl_FragData1 : COLOR1\n"
2678 ")\n"
2679 "{\n"
2680 "       // calculate viewspace pixel position\n"
2681 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2682 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2683 "       float3 position;\n"
2684 "#ifdef HLSL\n"
2685 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2686 "#else\n"
2687 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2688 "#endif\n"
2689 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2690 "       // decode viewspace pixel normal\n"
2691 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2692 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2693 "       // surfacenormal = pixel normal in viewspace\n"
2694 "       // LightVector = pixel to light in viewspace\n"
2695 "       // CubeVector = position in lightspace\n"
2696 "       // eyevector = pixel to view in viewspace\n"
2697 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2698 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2699 "#ifdef USEDIFFUSE\n"
2700 "       // calculate diffuse shading\n"
2701 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2702 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2703 "#endif\n"
2704 "#ifdef USESPECULAR\n"
2705 "       // calculate directional shading\n"
2706 "       float3 eyevector = position * -1.0;\n"
2707 "#  ifdef USEEXACTSPECULARMATH\n"
2708 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2709 "#  else\n"
2710 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2711 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2712 "#  endif\n"
2713 "#endif\n"
2714 "\n"
2715 "#if defined(USESHADOWMAP2D)\n"
2716 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2717 "#ifdef USESHADOWMAPVSDCT\n"
2718 ", Texture_CubeProjection\n"
2719 "#endif\n"
2720 "       ));\n"
2721 "#endif\n"
2722 "\n"
2723 "#ifdef USEDIFFUSE\n"
2724 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2725 "#else\n"
2726 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2727 "#endif\n"
2728 "#ifdef USESPECULAR\n"
2729 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2730 "#else\n"
2731 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2732 "#endif\n"
2733 "\n"
2734 "# ifdef USECUBEFILTER\n"
2735 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2736 "       gl_FragData0.rgb *= cubecolor;\n"
2737 "       gl_FragData1.rgb *= cubecolor;\n"
2738 "# endif\n"
2739 "}\n"
2740 "#endif // FRAGMENT_SHADER\n"
2741 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2742 "\n"
2743 "\n"
2744 "\n"
2745 "\n"
2746 "#ifdef VERTEX_SHADER\n"
2747 "void main\n"
2748 "(\n"
2749 "float4 gl_Vertex : POSITION,\n"
2750 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2751 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2752 "float4 gl_Color : COLOR0,\n"
2753 "#endif\n"
2754 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2755 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2756 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2757 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2758 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2759 "\n"
2760 "uniform float3 EyePosition : register(c24),\n"
2761 "uniform float4x4 TexMatrix : register(c0),\n"
2762 "#ifdef USEVERTEXTEXTUREBLEND\n"
2763 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2764 "#endif\n"
2765 "#ifdef MODE_LIGHTSOURCE\n"
2766 "uniform float4x4 ModelToLight : register(c20),\n"
2767 "#endif\n"
2768 "#ifdef MODE_LIGHTSOURCE\n"
2769 "uniform float3 LightPosition : register(c27),\n"
2770 "#endif\n"
2771 "#ifdef MODE_LIGHTDIRECTION\n"
2772 "uniform float3 LightDir : register(c26),\n"
2773 "#endif\n"
2774 "uniform float4 FogPlane : register(c25),\n"
2775 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2776 "uniform float3 LightPosition : register(c27),\n"
2777 "#endif\n"
2778 "#ifdef USESHADOWMAPORTHO\n"
2779 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2780 "#endif\n"
2781 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2782 "out float4 gl_FrontColor : COLOR,\n"
2783 "#endif\n"
2784 "out float4 TexCoordBoth : TEXCOORD0,\n"
2785 "#ifdef USELIGHTMAP\n"
2786 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2787 "#endif\n"
2788 "#ifdef USEEYEVECTOR\n"
2789 "out float3 EyeVector : TEXCOORD2,\n"
2790 "#endif\n"
2791 "#ifdef USEREFLECTION\n"
2792 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2793 "#endif\n"
2794 "#ifdef USEFOG\n"
2795 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2796 "#endif\n"
2797 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2798 "out float3 LightVector : TEXCOORD1,\n"
2799 "#endif\n"
2800 "#ifdef MODE_LIGHTSOURCE\n"
2801 "out float3 CubeVector : TEXCOORD3,\n"
2802 "#endif\n"
2803 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2804 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2805 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2806 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2807 "#endif\n"
2808 "#ifdef USESHADOWMAPORTHO\n"
2809 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2810 "#endif\n"
2811 "out float4 gl_Position : POSITION\n"
2812 ")\n"
2813 "{\n"
2814 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2815 "#ifdef HLSL\n"
2816 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2817 "#else\n"
2818 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2819 "#endif\n"
2820 "#endif\n"
2821 "       // copy the surface texcoord\n"
2822 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2823 "#ifdef USEVERTEXTEXTUREBLEND\n"
2824 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2825 "#endif\n"
2826 "#ifdef USELIGHTMAP\n"
2827 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2828 "#endif\n"
2829 "\n"
2830 "#ifdef MODE_LIGHTSOURCE\n"
2831 "       // transform vertex position into light attenuation/cubemap space\n"
2832 "       // (-1 to +1 across the light box)\n"
2833 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2834 "\n"
2835 "# ifdef USEDIFFUSE\n"
2836 "       // transform unnormalized light direction into tangent space\n"
2837 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2838 "       //  normalize it per pixel)\n"
2839 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2840 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2841 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2842 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2843 "# endif\n"
2844 "#endif\n"
2845 "\n"
2846 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2847 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2848 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2849 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2850 "#endif\n"
2851 "\n"
2852 "       // transform unnormalized eye direction into tangent space\n"
2853 "#ifdef USEEYEVECTOR\n"
2854 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2855 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2856 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2857 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2858 "#endif\n"
2859 "\n"
2860 "#ifdef USEFOG\n"
2861 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2862 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2863 "#endif\n"
2864 "\n"
2865 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2866 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2867 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2868 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2869 "#endif\n"
2870 "\n"
2871 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2872 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2873 "\n"
2874 "#ifdef USESHADOWMAPORTHO\n"
2875 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2876 "#endif\n"
2877 "\n"
2878 "#ifdef USEREFLECTION\n"
2879 "       ModelViewProjectionPosition = gl_Position;\n"
2880 "#endif\n"
2881 "}\n"
2882 "#endif // VERTEX_SHADER\n"
2883 "\n"
2884 "\n"
2885 "\n"
2886 "\n"
2887 "#ifdef FRAGMENT_SHADER\n"
2888 "void main\n"
2889 "(\n"
2890 "#ifdef USEDEFERREDLIGHTMAP\n"
2891 "#ifdef HLSL\n"
2892 "float2 Pixel : VPOS,\n"
2893 "#else\n"
2894 "float2 Pixel : WPOS,\n"
2895 "#endif\n"
2896 "#endif\n"
2897 "float4 gl_FrontColor : COLOR,\n"
2898 "float4 TexCoordBoth : TEXCOORD0,\n"
2899 "#ifdef USELIGHTMAP\n"
2900 "float2 TexCoordLightmap : TEXCOORD1,\n"
2901 "#endif\n"
2902 "#ifdef USEEYEVECTOR\n"
2903 "float3 EyeVector : TEXCOORD2,\n"
2904 "#endif\n"
2905 "#ifdef USEREFLECTION\n"
2906 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2907 "#endif\n"
2908 "#ifdef USEFOG\n"
2909 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2910 "#endif\n"
2911 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2912 "float3 LightVector : TEXCOORD1,\n"
2913 "#endif\n"
2914 "#ifdef MODE_LIGHTSOURCE\n"
2915 "float3 CubeVector : TEXCOORD3,\n"
2916 "#endif\n"
2917 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2918 "float4 ModelViewPosition : TEXCOORD0,\n"
2919 "#endif\n"
2920 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2921 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2922 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2923 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2924 "#endif\n"
2925 "#ifdef USESHADOWMAPORTHO\n"
2926 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2927 "#endif\n"
2928 "\n"
2929 "uniform sampler Texture_Normal : register(s0),\n"
2930 "uniform sampler Texture_Color : register(s1),\n"
2931 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2932 "uniform sampler Texture_Gloss : register(s2),\n"
2933 "#endif\n"
2934 "#ifdef USEGLOW\n"
2935 "uniform sampler Texture_Glow : register(s3),\n"
2936 "#endif\n"
2937 "#ifdef USEVERTEXTEXTUREBLEND\n"
2938 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2939 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2940 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2941 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2942 "#endif\n"
2943 "#ifdef USEGLOW\n"
2944 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2945 "#endif\n"
2946 "#endif\n"
2947 "#ifdef USECOLORMAPPING\n"
2948 "uniform sampler Texture_Pants : register(s4),\n"
2949 "uniform sampler Texture_Shirt : register(s7),\n"
2950 "#endif\n"
2951 "#ifdef USEFOG\n"
2952 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2953 "uniform sampler Texture_FogMask : register(s8),\n"
2954 "#endif\n"
2955 "#ifdef USELIGHTMAP\n"
2956 "uniform sampler Texture_Lightmap : register(s9),\n"
2957 "#endif\n"
2958 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2959 "uniform sampler Texture_Deluxemap : register(s10),\n"
2960 "#endif\n"
2961 "#ifdef USEREFLECTION\n"
2962 "uniform sampler Texture_Reflection : register(s7),\n"
2963 "#endif\n"
2964 "\n"
2965 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2966 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2967 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2968 "#endif\n"
2969 "#ifdef USEDEFERREDLIGHTMAP\n"
2970 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2971 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2972 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2973 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2974 "#endif\n"
2975 "\n"
2976 "#ifdef USECOLORMAPPING\n"
2977 "uniform half3 Color_Pants : register(c7),\n"
2978 "uniform half3 Color_Shirt : register(c8),\n"
2979 "#endif\n"
2980 "#ifdef USEFOG\n"
2981 "uniform float3 FogColor : register(c16),\n"
2982 "uniform float FogRangeRecip : register(c20),\n"
2983 "uniform float FogPlaneViewDist : register(c19),\n"
2984 "uniform float FogHeightFade : register(c17),\n"
2985 "#endif\n"
2986 "\n"
2987 "#ifdef USEOFFSETMAPPING\n"
2988 "uniform float OffsetMapping_Scale : register(c24),\n"
2989 "#endif\n"
2990 "\n"
2991 "#ifdef USEDEFERREDLIGHTMAP\n"
2992 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2993 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
2994 "uniform half3 DeferredMod_Specular : register(c13),\n"
2995 "#endif\n"
2996 "uniform half3 Color_Ambient : register(c3),\n"
2997 "uniform half3 Color_Diffuse : register(c4),\n"
2998 "uniform half3 Color_Specular : register(c5),\n"
2999 "uniform half SpecularPower : register(c36),\n"
3000 "#ifdef USEGLOW\n"
3001 "uniform half3 Color_Glow : register(c6),\n"
3002 "#endif\n"
3003 "uniform half Alpha : register(c0),\n"
3004 "#ifdef USEREFLECTION\n"
3005 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3006 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3007 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3008 "uniform half4 ReflectColor : register(c26),\n"
3009 "#endif\n"
3010 "#ifdef USEREFLECTCUBE\n"
3011 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3012 "uniform sampler Texture_ReflectMask : register(s5),\n"
3013 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3014 "#endif\n"
3015 "#ifdef MODE_LIGHTDIRECTION\n"
3016 "uniform half3 LightColor : register(c21),\n"
3017 "#endif\n"
3018 "#ifdef MODE_LIGHTSOURCE\n"
3019 "uniform half3 LightColor : register(c21),\n"
3020 "#endif\n"
3021 "\n"
3022 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3023 "uniform sampler Texture_Attenuation : register(s9),\n"
3024 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3025 "#endif\n"
3026 "\n"
3027 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3028 "\n"
3029 "#ifdef USESHADOWMAP2D\n"
3030 "# ifdef USESHADOWSAMPLER\n"
3031 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3032 "# else\n"
3033 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3034 "# endif\n"
3035 "#endif\n"
3036 "\n"
3037 "#ifdef USESHADOWMAPVSDCT\n"
3038 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3039 "#endif\n"
3040 "\n"
3041 "#if defined(USESHADOWMAP2D)\n"
3042 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3043 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3044 "#endif\n"
3045 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3046 "\n"
3047 "out float4 gl_FragColor : COLOR\n"
3048 ")\n"
3049 "{\n"
3050 "       float2 TexCoord = TexCoordBoth.xy;\n"
3051 "#ifdef USEVERTEXTEXTUREBLEND\n"
3052 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3053 "#endif\n"
3054 "#ifdef USEOFFSETMAPPING\n"
3055 "       // apply offsetmapping\n"
3056 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3057 "#define TexCoord TexCoordOffset\n"
3058 "#endif\n"
3059 "\n"
3060 "       // combine the diffuse textures (base, pants, shirt)\n"
3061 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3062 "#ifdef USEALPHAKILL\n"
3063 "       if (color.a < 0.5)\n"
3064 "               discard;\n"
3065 "#endif\n"
3066 "       color.a *= Alpha;\n"
3067 "#ifdef USECOLORMAPPING\n"
3068 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3069 "#endif\n"
3070 "#ifdef USEVERTEXTEXTUREBLEND\n"
3071 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3072 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3073 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3074 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3075 "       color.a = 1.0;\n"
3076 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3077 "#endif\n"
3078 "\n"
3079 "       // get the surface normal\n"
3080 "#ifdef USEVERTEXTEXTUREBLEND\n"
3081 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3082 "#else\n"
3083 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3084 "#endif\n"
3085 "\n"
3086 "       // get the material colors\n"
3087 "       half3 diffusetex = color.rgb;\n"
3088 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3089 "# ifdef USEVERTEXTEXTUREBLEND\n"
3090 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3091 "# else\n"
3092 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3093 "# endif\n"
3094 "#endif\n"
3095 "\n"
3096 "#ifdef USEREFLECTCUBE\n"
3097 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3098 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3099 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3100 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3101 "#endif\n"
3102 "\n"
3103 "\n"
3104 "\n"
3105 "\n"
3106 "#ifdef MODE_LIGHTSOURCE\n"
3107 "       // light source\n"
3108 "#ifdef USEDIFFUSE\n"
3109 "       half3 lightnormal = half3(normalize(LightVector));\n"
3110 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3111 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3112 "#ifdef USESPECULAR\n"
3113 "#ifdef USEEXACTSPECULARMATH\n"
3114 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3115 "#else\n"
3116 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3117 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3118 "#endif\n"
3119 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3120 "#endif\n"
3121 "#else\n"
3122 "       color.rgb = diffusetex * Color_Ambient;\n"
3123 "#endif\n"
3124 "       color.rgb *= LightColor;\n"
3125 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3126 "#if defined(USESHADOWMAP2D)\n"
3127 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3128 "#ifdef USESHADOWMAPVSDCT\n"
3129 ", Texture_CubeProjection\n"
3130 "#endif\n"
3131 "       ));\n"
3132 "\n"
3133 "#endif\n"
3134 "# ifdef USECUBEFILTER\n"
3135 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3136 "# endif\n"
3137 "\n"
3138 "#ifdef USESHADOWMAP2D\n"
3139 "#ifdef USESHADOWMAPVSDCT\n"
3140 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3141 "#else\n"
3142 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3143 "#endif\n"
3144 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3145 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3146 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3147 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3148 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3149 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3150 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3151 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3152 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3153 "//     color.r = half(shadowmaptc.z);\n"
3154 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3155 "//     color.r = half(shadowmaptc.z);\n"
3156 "//     color.r = 1;\n"
3157 "//     color.rgb = abs(CubeVector);\n"
3158 "#endif\n"
3159 "//     color.rgb = half3(1,1,1);\n"
3160 "#endif // MODE_LIGHTSOURCE\n"
3161 "\n"
3162 "\n"
3163 "\n"
3164 "\n"
3165 "#ifdef MODE_LIGHTDIRECTION\n"
3166 "#define SHADING\n"
3167 "#ifdef USEDIFFUSE\n"
3168 "       half3 lightnormal = half3(normalize(LightVector));\n"
3169 "#endif\n"
3170 "#define lightcolor LightColor\n"
3171 "#endif // MODE_LIGHTDIRECTION\n"
3172 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3173 "#define SHADING\n"
3174 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3175 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3176 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3177 "       // convert modelspace light vector to tangentspace\n"
3178 "       half3 lightnormal;\n"
3179 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3180 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3181 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3182 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3183 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3184 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3185 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3186 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3187 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3188 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3189 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3190 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3191 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3192 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3193 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3194 "#define SHADING\n"
3195 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3196 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3197 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3198 "#endif\n"
3199 "\n"
3200 "\n"
3201 "\n"
3202 "\n"
3203 "#ifdef MODE_FAKELIGHT\n"
3204 "#define SHADING\n"
3205 "half3 lightnormal = half3(normalize(EyeVector));\n"
3206 "half3 lightcolor = half3(1.0);\n"
3207 "#endif // MODE_FAKELIGHT\n"
3208 "\n"
3209 "\n"
3210 "\n"
3211 "\n"
3212 "#ifdef MODE_LIGHTMAP\n"
3213 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3214 "#endif // MODE_LIGHTMAP\n"
3215 "#ifdef MODE_VERTEXCOLOR\n"
3216 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3217 "#endif // MODE_VERTEXCOLOR\n"
3218 "#ifdef MODE_FLATCOLOR\n"
3219 "       color.rgb = diffusetex * Color_Ambient;\n"
3220 "#endif // MODE_FLATCOLOR\n"
3221 "\n"
3222 "\n"
3223 "\n"
3224 "\n"
3225 "#ifdef SHADING\n"
3226 "# ifdef USEDIFFUSE\n"
3227 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3228 "#  ifdef USESPECULAR\n"
3229 "#   ifdef USEEXACTSPECULARMATH\n"
3230 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3231 "#   else\n"
3232 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3233 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3234 "#   endif\n"
3235 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3236 "#  else\n"
3237 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3238 "#  endif\n"
3239 "# else\n"
3240 "       color.rgb = diffusetex * Color_Ambient;\n"
3241 "# endif\n"
3242 "#endif\n"
3243 "\n"
3244 "#ifdef USESHADOWMAPORTHO\n"
3245 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3246 "#endif\n"
3247 "\n"
3248 "#ifdef USEDEFERREDLIGHTMAP\n"
3249 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3250 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3251 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3252 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3253 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3254 "#endif\n"
3255 "\n"
3256 "#ifdef USEGLOW\n"
3257 "#ifdef USEVERTEXTEXTUREBLEND\n"
3258 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3259 "#else\n"
3260 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3261 "#endif\n"
3262 "#endif\n"
3263 "\n"
3264 "#ifdef USEFOG\n"
3265 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3266 "#endif\n"
3267 "\n"
3268 "       // 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"
3269 "#ifdef USEREFLECTION\n"
3270 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3271 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3272 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3273 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3274 "       // FIXME temporary hack to detect the case that the reflection\n"
3275 "       // gets blackened at edges due to leaving the area that contains actual\n"
3276 "       // content.\n"
3277 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3278 "       // 'appening.\n"
3279 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3280 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3281 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3282 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3283 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3284 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3285 "#endif\n"
3286 "\n"
3287 "       gl_FragColor = float4(color);\n"
3288 "}\n"
3289 "#endif // FRAGMENT_SHADER\n"
3290 "\n"
3291 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3292 "#endif // !MODE_DEFERREDGEOMETRY\n"
3293 "#endif // !MODE_WATER\n"
3294 "#endif // !MODE_REFRACTION\n"
3295 "#endif // !MODE_BLOOMBLUR\n"
3296 "#endif // !MODE_GENERIC\n"
3297 "#endif // !MODE_POSTPROCESS\n"
3298 "#endif // !MODE_SHOWDEPTH\n"
3299 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3300 ;
3301
3302 char *glslshaderstring = NULL;
3303 char *cgshaderstring = NULL;
3304 char *hlslshaderstring = NULL;
3305
3306 //=======================================================================================================================================================
3307
3308 typedef struct shaderpermutationinfo_s
3309 {
3310         const char *pretext;
3311         const char *name;
3312 }
3313 shaderpermutationinfo_t;
3314
3315 typedef struct shadermodeinfo_s
3316 {
3317         const char *vertexfilename;
3318         const char *geometryfilename;
3319         const char *fragmentfilename;
3320         const char *pretext;
3321         const char *name;
3322 }
3323 shadermodeinfo_t;
3324
3325 typedef enum shaderpermutation_e
3326 {
3327         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3328         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3329         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3330         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3331         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3332         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3333         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3334         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3335         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3336         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3337         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3338         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3339         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3340         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3341         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3342         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3343         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3344         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3345         SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3346         SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3347         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3348         SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3349         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3350         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3351         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3352         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3353         SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3354         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3355         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3356 }
3357 shaderpermutation_t;
3358
3359 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3360 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3361 {
3362         {"#define USEDIFFUSE\n", " diffuse"},
3363         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3364         {"#define USEVIEWTINT\n", " viewtint"},
3365         {"#define USECOLORMAPPING\n", " colormapping"},
3366         {"#define USESATURATION\n", " saturation"},
3367         {"#define USEFOGINSIDE\n", " foginside"},
3368         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3369         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3370         {"#define USEGAMMARAMPS\n", " gammaramps"},
3371         {"#define USECUBEFILTER\n", " cubefilter"},
3372         {"#define USEGLOW\n", " glow"},
3373         {"#define USEBLOOM\n", " bloom"},
3374         {"#define USESPECULAR\n", " specular"},
3375         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3376         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3377         {"#define USEREFLECTION\n", " reflection"},
3378         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3379         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3380         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3381         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3382         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3383         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3384         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3385         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3386         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3387         {"#define USEALPHAKILL\n", " alphakill"},
3388         {"#define USEREFLECTCUBE\n", " reflectcube"},
3389 };
3390
3391 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3392 typedef enum shadermode_e
3393 {
3394         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3395         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3396         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3397         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3398         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3399         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3400         SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3401         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3402         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3403         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3404         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3405         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3406         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3407         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3408         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3409         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3410         SHADERMODE_COUNT
3411 }
3412 shadermode_t;
3413
3414 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3415 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3416 {
3417         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3418         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3419         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3420         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3421         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3422         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3423         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3424         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3425         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3426         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3427         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3428         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3429         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3430         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3431         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3432         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3433 };
3434
3435 #ifdef SUPPORTCG
3436 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3437 {
3438         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3439         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3440         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3441         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3442         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3443         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3444         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3445         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3446         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3447         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3448         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3449         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3450         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3451         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3452         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3453         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3454 };
3455 #endif
3456
3457 #ifdef SUPPORTD3D
3458 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3459 {
3460         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3461         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3462         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3463         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3464         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3465         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3466         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3467         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3468         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3469         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3470         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3471         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3472         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3473         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3474         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3475 };
3476 #endif
3477
3478 struct r_glsl_permutation_s;
3479 typedef struct r_glsl_permutation_s
3480 {
3481         /// hash lookup data
3482         struct r_glsl_permutation_s *hashnext;
3483         unsigned int mode;
3484         unsigned int permutation;
3485
3486         /// indicates if we have tried compiling this permutation already
3487         qboolean compiled;
3488         /// 0 if compilation failed
3489         int program;
3490         /// locations of detected uniforms in program object, or -1 if not found
3491         int loc_Texture_First;
3492         int loc_Texture_Second;
3493         int loc_Texture_GammaRamps;
3494         int loc_Texture_Normal;
3495         int loc_Texture_Color;
3496         int loc_Texture_Gloss;
3497         int loc_Texture_Glow;
3498         int loc_Texture_SecondaryNormal;
3499         int loc_Texture_SecondaryColor;
3500         int loc_Texture_SecondaryGloss;
3501         int loc_Texture_SecondaryGlow;
3502         int loc_Texture_Pants;
3503         int loc_Texture_Shirt;
3504         int loc_Texture_FogHeightTexture;
3505         int loc_Texture_FogMask;
3506         int loc_Texture_Lightmap;
3507         int loc_Texture_Deluxemap;
3508         int loc_Texture_Attenuation;
3509         int loc_Texture_Cube;
3510         int loc_Texture_Refraction;
3511         int loc_Texture_Reflection;
3512         int loc_Texture_ShadowMap2D;
3513         int loc_Texture_CubeProjection;
3514         int loc_Texture_ScreenDepth;
3515         int loc_Texture_ScreenNormalMap;
3516         int loc_Texture_ScreenDiffuse;
3517         int loc_Texture_ScreenSpecular;
3518         int loc_Texture_ReflectMask;
3519         int loc_Texture_ReflectCube;
3520         int loc_Alpha;
3521         int loc_BloomBlur_Parameters;
3522         int loc_ClientTime;
3523         int loc_Color_Ambient;
3524         int loc_Color_Diffuse;
3525         int loc_Color_Specular;
3526         int loc_Color_Glow;
3527         int loc_Color_Pants;
3528         int loc_Color_Shirt;
3529         int loc_DeferredColor_Ambient;
3530         int loc_DeferredColor_Diffuse;
3531         int loc_DeferredColor_Specular;
3532         int loc_DeferredMod_Diffuse;
3533         int loc_DeferredMod_Specular;
3534         int loc_DistortScaleRefractReflect;
3535         int loc_EyePosition;
3536         int loc_FogColor;
3537         int loc_FogHeightFade;
3538         int loc_FogPlane;
3539         int loc_FogPlaneViewDist;
3540         int loc_FogRangeRecip;
3541         int loc_LightColor;
3542         int loc_LightDir;
3543         int loc_LightPosition;
3544         int loc_OffsetMapping_Scale;
3545         int loc_PixelSize;
3546         int loc_ReflectColor;
3547         int loc_ReflectFactor;
3548         int loc_ReflectOffset;
3549         int loc_RefractColor;
3550         int loc_Saturation;
3551         int loc_ScreenCenterRefractReflect;
3552         int loc_ScreenScaleRefractReflect;
3553         int loc_ScreenToDepth;
3554         int loc_ShadowMap_Parameters;
3555         int loc_ShadowMap_TextureScale;
3556         int loc_SpecularPower;
3557         int loc_UserVec1;
3558         int loc_UserVec2;
3559         int loc_UserVec3;
3560         int loc_UserVec4;
3561         int loc_ViewTintColor;
3562         int loc_ViewToLight;
3563         int loc_ModelToLight;
3564         int loc_TexMatrix;
3565         int loc_BackgroundTexMatrix;
3566         int loc_ModelViewProjectionMatrix;
3567         int loc_ModelViewMatrix;
3568         int loc_PixelToScreenTexCoord;
3569         int loc_ModelToReflectCube;
3570         int loc_ShadowMapMatrix;
3571         int loc_BloomColorSubtract;
3572 }
3573 r_glsl_permutation_t;
3574
3575 #define SHADERPERMUTATION_HASHSIZE 256
3576
3577 // this called both on R_GLSL_CompileShader and R_HLSL_CacheShader
3578 // this function adds more "#define" to supply static parms, could be used by game-specific code part
3579 int vertstrings_count = 0;
3580 int geomstrings_count = 0;
3581 int fragstrings_count = 0;
3582 const char *vertstrings_list[64+3];
3583 const char *geomstrings_list[64+3];
3584 const char *fragstrings_list[64+3];
3585 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3586 {
3587         if (mode == SHADERMODE_POSTPROCESS && (permutation & SHADERPERMUTATION_SATURATION))
3588                 if (r_glsl_saturation_redcompensate.integer)
3589                         fragstrings_list[fragstrings_count++] = "#define SATURATION_REDCOMPENSATE\n";
3590 }
3591
3592 /// information about each possible shader permutation
3593 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3594 /// currently selected permutation
3595 r_glsl_permutation_t *r_glsl_permutation;
3596 /// storage for permutations linked in the hash table
3597 memexpandablearray_t r_glsl_permutationarray;
3598
3599 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3600 {
3601         //unsigned int hashdepth = 0;
3602         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3603         r_glsl_permutation_t *p;
3604         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3605         {
3606                 if (p->mode == mode && p->permutation == permutation)
3607                 {
3608                         //if (hashdepth > 10)
3609                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3610                         return p;
3611                 }
3612                 //hashdepth++;
3613         }
3614         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3615         p->mode = mode;
3616         p->permutation = permutation;
3617         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3618         r_glsl_permutationhash[mode][hashindex] = p;
3619         //if (hashdepth > 10)
3620         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3621         return p;
3622 }
3623
3624 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3625 {
3626         char *shaderstring;
3627         if (!filename || !filename[0])
3628                 return NULL;
3629         if (!strcmp(filename, "glsl/default.glsl"))
3630         {
3631                 if (!glslshaderstring)
3632                 {
3633                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3634                         if (glslshaderstring)
3635                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3636                         else
3637                                 glslshaderstring = (char *)builtinshaderstring;
3638                 }
3639                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3640                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3641                 return shaderstring;
3642         }
3643         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3644         if (shaderstring)
3645         {
3646                 if (printfromdisknotice)
3647                         Con_DPrintf("from disk %s... ", filename);
3648                 return shaderstring;
3649         }
3650         return shaderstring;
3651 }
3652
3653 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3654 {
3655         int i;
3656         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3657         char *vertexstring, *geometrystring, *fragmentstring;
3658         char permutationname[256];
3659
3660         if (p->compiled)
3661                 return;
3662         p->compiled = true;
3663         p->program = 0;
3664
3665         permutationname[0] = 0;
3666         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3667         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3668         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3669
3670         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3671
3672         // the first pretext is which type of shader to compile as
3673         // (later these will all be bound together as a program object)
3674         vertstrings_count = 0;
3675         geomstrings_count = 0;
3676         fragstrings_count = 0;
3677         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3678         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3679         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3680
3681         // the second pretext is the mode (for example a light source)
3682         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3683         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3684         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3685         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3686
3687         // now add all the permutation pretexts
3688         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3689         {
3690                 if (permutation & (1<<i))
3691                 {
3692                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3693                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3694                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3695                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3696                 }
3697                 else
3698                 {
3699                         // keep line numbers correct
3700                         vertstrings_list[vertstrings_count++] = "\n";
3701                         geomstrings_list[geomstrings_count++] = "\n";
3702                         fragstrings_list[fragstrings_count++] = "\n";
3703                 }
3704         }
3705
3706         // add static parms
3707         R_CompileShader_AddStaticParms(mode, permutation);
3708
3709         // now append the shader text itself
3710         vertstrings_list[vertstrings_count++] = vertexstring;
3711         geomstrings_list[geomstrings_count++] = geometrystring;
3712         fragstrings_list[fragstrings_count++] = fragmentstring;
3713
3714         // if any sources were NULL, clear the respective list
3715         if (!vertexstring)
3716                 vertstrings_count = 0;
3717         if (!geometrystring)
3718                 geomstrings_count = 0;
3719         if (!fragmentstring)
3720                 fragstrings_count = 0;
3721
3722         // compile the shader program
3723         if (vertstrings_count + geomstrings_count + fragstrings_count)
3724                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3725         if (p->program)
3726         {
3727                 CHECKGLERROR
3728                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3729                 // look up all the uniform variable names we care about, so we don't
3730                 // have to look them up every time we set them
3731
3732                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3733                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3734                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3735                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3736                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3737                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3738                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3739                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3740                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3741                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3742                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3743                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3744                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3745                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3746                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3747                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3748                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3749                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3750                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3751                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3752                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3753                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3754                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3755                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3756                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3757                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3758                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3759                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3760                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3761                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3762                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3763                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3764                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3765                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3766                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3767                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3768                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3769                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3770                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3771                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3772                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3773                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3774                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3775                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3776                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3777                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3778                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3779                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3780                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3781                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3782                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3783                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3784                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3785                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3786                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3787                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3788                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3789                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3790                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3791                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3792                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3793                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3794                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3795                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3796                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3797                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3798                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3799                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3800                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3801                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3802                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3803                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3804                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3805                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3806                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3807                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3808                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3809                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3810                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3811                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3812                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3813                 // initialize the samplers to refer to the texture units we use
3814                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3815                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3816                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3817                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3818                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3819                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3820                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3821                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3822                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3823                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3824                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3825                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3826                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3827                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3828                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3829                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3830                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3831                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3832                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3833                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3834                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3835                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3836                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3837                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3838                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3839                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3840                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3841                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3842                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3843                 CHECKGLERROR
3844                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3845         }
3846         else
3847                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3848
3849         // free the strings
3850         if (vertexstring)
3851                 Mem_Free(vertexstring);
3852         if (geometrystring)
3853                 Mem_Free(geometrystring);
3854         if (fragmentstring)
3855                 Mem_Free(fragmentstring);
3856 }
3857
3858 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3859 {
3860         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3861         if (r_glsl_permutation != perm)
3862         {
3863                 r_glsl_permutation = perm;
3864                 if (!r_glsl_permutation->program)
3865                 {
3866                         if (!r_glsl_permutation->compiled)
3867                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3868                         if (!r_glsl_permutation->program)
3869                         {
3870                                 // remove features until we find a valid permutation
3871                                 int i;
3872                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3873                                 {
3874                                         // reduce i more quickly whenever it would not remove any bits
3875                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3876                                         if (!(permutation & j))
3877                                                 continue;
3878                                         permutation -= j;
3879                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3880                                         if (!r_glsl_permutation->compiled)
3881                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3882                                         if (r_glsl_permutation->program)
3883                                                 break;
3884                                 }
3885                                 if (i >= SHADERPERMUTATION_COUNT)
3886                                 {
3887                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3888                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3889                                         qglUseProgramObjectARB(0);CHECKGLERROR
3890                                         return; // no bit left to clear, entire mode is broken
3891                                 }
3892                         }
3893                 }
3894                 CHECKGLERROR
3895                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3896         }
3897         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3898         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3899         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3900 }
3901
3902 #ifdef SUPPORTCG
3903 #include <Cg/cgGL.h>
3904 struct r_cg_permutation_s;
3905 typedef struct r_cg_permutation_s
3906 {
3907         /// hash lookup data
3908         struct r_cg_permutation_s *hashnext;
3909         unsigned int mode;
3910         unsigned int permutation;
3911
3912         /// indicates if we have tried compiling this permutation already
3913         qboolean compiled;
3914         /// 0 if compilation failed
3915         CGprogram vprogram;
3916         CGprogram fprogram;
3917         /// locations of detected parameters in programs, or NULL if not found
3918         CGparameter vp_EyePosition;
3919         CGparameter vp_FogPlane;
3920         CGparameter vp_LightDir;
3921         CGparameter vp_LightPosition;
3922         CGparameter vp_ModelToLight;
3923         CGparameter vp_TexMatrix;
3924         CGparameter vp_BackgroundTexMatrix;
3925         CGparameter vp_ModelViewProjectionMatrix;
3926         CGparameter vp_ModelViewMatrix;
3927         CGparameter vp_ShadowMapMatrix;
3928
3929         CGparameter fp_Texture_First;
3930         CGparameter fp_Texture_Second;
3931         CGparameter fp_Texture_GammaRamps;
3932         CGparameter fp_Texture_Normal;
3933         CGparameter fp_Texture_Color;
3934         CGparameter fp_Texture_Gloss;
3935         CGparameter fp_Texture_Glow;
3936         CGparameter fp_Texture_SecondaryNormal;
3937         CGparameter fp_Texture_SecondaryColor;
3938         CGparameter fp_Texture_SecondaryGloss;
3939         CGparameter fp_Texture_SecondaryGlow;
3940         CGparameter fp_Texture_Pants;
3941         CGparameter fp_Texture_Shirt;
3942         CGparameter fp_Texture_FogHeightTexture;
3943         CGparameter fp_Texture_FogMask;
3944         CGparameter fp_Texture_Lightmap;
3945         CGparameter fp_Texture_Deluxemap;
3946         CGparameter fp_Texture_Attenuation;
3947         CGparameter fp_Texture_Cube;
3948         CGparameter fp_Texture_Refraction;
3949         CGparameter fp_Texture_Reflection;
3950         CGparameter fp_Texture_ShadowMap2D;
3951         CGparameter fp_Texture_CubeProjection;
3952         CGparameter fp_Texture_ScreenDepth;
3953         CGparameter fp_Texture_ScreenNormalMap;
3954         CGparameter fp_Texture_ScreenDiffuse;
3955         CGparameter fp_Texture_ScreenSpecular;
3956         CGparameter fp_Texture_ReflectMask;
3957         CGparameter fp_Texture_ReflectCube;
3958         CGparameter fp_Alpha;
3959         CGparameter fp_BloomBlur_Parameters;
3960         CGparameter fp_ClientTime;
3961         CGparameter fp_Color_Ambient;
3962         CGparameter fp_Color_Diffuse;
3963         CGparameter fp_Color_Specular;
3964         CGparameter fp_Color_Glow;
3965         CGparameter fp_Color_Pants;
3966         CGparameter fp_Color_Shirt;
3967         CGparameter fp_DeferredColor_Ambient;
3968         CGparameter fp_DeferredColor_Diffuse;
3969         CGparameter fp_DeferredColor_Specular;
3970         CGparameter fp_DeferredMod_Diffuse;
3971         CGparameter fp_DeferredMod_Specular;
3972         CGparameter fp_DistortScaleRefractReflect;
3973         CGparameter fp_EyePosition;
3974         CGparameter fp_FogColor;
3975         CGparameter fp_FogHeightFade;
3976         CGparameter fp_FogPlane;
3977         CGparameter fp_FogPlaneViewDist;
3978         CGparameter fp_FogRangeRecip;
3979         CGparameter fp_LightColor;
3980         CGparameter fp_LightDir;
3981         CGparameter fp_LightPosition;
3982         CGparameter fp_OffsetMapping_Scale;
3983         CGparameter fp_PixelSize;
3984         CGparameter fp_ReflectColor;
3985         CGparameter fp_ReflectFactor;
3986         CGparameter fp_ReflectOffset;
3987         CGparameter fp_RefractColor;
3988         CGparameter fp_Saturation;
3989         CGparameter fp_ScreenCenterRefractReflect;
3990         CGparameter fp_ScreenScaleRefractReflect;
3991         CGparameter fp_ScreenToDepth;
3992         CGparameter fp_ShadowMap_Parameters;
3993         CGparameter fp_ShadowMap_TextureScale;
3994         CGparameter fp_SpecularPower;
3995         CGparameter fp_UserVec1;
3996         CGparameter fp_UserVec2;
3997         CGparameter fp_UserVec3;
3998         CGparameter fp_UserVec4;
3999         CGparameter fp_ViewTintColor;
4000         CGparameter fp_ViewToLight;
4001         CGparameter fp_PixelToScreenTexCoord;
4002         CGparameter fp_ModelToReflectCube;
4003         CGparameter fp_BloomColorSubtract;
4004 }
4005 r_cg_permutation_t;
4006
4007 /// information about each possible shader permutation
4008 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4009 /// currently selected permutation
4010 r_cg_permutation_t *r_cg_permutation;
4011 /// storage for permutations linked in the hash table
4012 memexpandablearray_t r_cg_permutationarray;
4013
4014 #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));}}
4015
4016 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4017 {
4018         //unsigned int hashdepth = 0;
4019         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4020         r_cg_permutation_t *p;
4021         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4022         {
4023                 if (p->mode == mode && p->permutation == permutation)
4024                 {
4025                         //if (hashdepth > 10)
4026                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4027                         return p;
4028                 }
4029                 //hashdepth++;
4030         }
4031         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4032         p->mode = mode;
4033         p->permutation = permutation;
4034         p->hashnext = r_cg_permutationhash[mode][hashindex];
4035         r_cg_permutationhash[mode][hashindex] = p;
4036         //if (hashdepth > 10)
4037         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4038         return p;
4039 }
4040
4041 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4042 {
4043         char *shaderstring;
4044         if (!filename || !filename[0])
4045                 return NULL;
4046         if (!strcmp(filename, "cg/default.cg"))
4047         {
4048                 if (!cgshaderstring)
4049                 {
4050                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4051                         if (cgshaderstring)
4052                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4053                         else
4054                                 cgshaderstring = (char *)builtincgshaderstring;
4055                 }
4056                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4057                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4058                 return shaderstring;
4059         }
4060         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4061         if (shaderstring)
4062         {
4063                 if (printfromdisknotice)
4064                         Con_DPrintf("from disk %s... ", filename);
4065                 return shaderstring;
4066         }
4067         return shaderstring;
4068 }
4069
4070 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4071 {
4072         // TODO: load or create .fp and .vp shader files
4073 }
4074
4075 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4076 {
4077         int i;
4078         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4079         int vertstring_length = 0;
4080         int geomstring_length = 0;
4081         int fragstring_length = 0;
4082         char *t;
4083         char *vertexstring, *geometrystring, *fragmentstring;
4084         char *vertstring, *geomstring, *fragstring;
4085         char permutationname[256];
4086         char cachename[256];
4087         CGprofile vertexProfile;
4088         CGprofile fragmentProfile;
4089
4090         if (p->compiled)
4091                 return;
4092         p->compiled = true;
4093         p->vprogram = NULL;
4094         p->fprogram = NULL;
4095
4096         permutationname[0] = 0;
4097         cachename[0] = 0;
4098         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4099         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4100         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4101
4102         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4103         strlcat(cachename, "cg/", sizeof(cachename));
4104
4105         // the first pretext is which type of shader to compile as
4106         // (later these will all be bound together as a program object)
4107         vertstrings_count = 0;
4108         geomstrings_count = 0;
4109         fragstrings_count = 0;
4110         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4111         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4112         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4113
4114         // the second pretext is the mode (for example a light source)
4115         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4116         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4117         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4118         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4119         strlcat(cachename, modeinfo->name, sizeof(cachename));
4120
4121         // now add all the permutation pretexts
4122         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4123         {
4124                 if (permutation & (1<<i))
4125                 {
4126                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4127                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4128                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4129                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4130                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4131                 }
4132                 else
4133                 {
4134                         // keep line numbers correct
4135                         vertstrings_list[vertstrings_count++] = "\n";
4136                         geomstrings_list[geomstrings_count++] = "\n";
4137                         fragstrings_list[fragstrings_count++] = "\n";
4138                 }
4139         }
4140
4141         // add static parms
4142         R_CompileShader_AddStaticParms(mode, permutation);
4143
4144         // replace spaces in the cachename with _ characters
4145         for (i = 0;cachename[i];i++)
4146                 if (cachename[i] == ' ')
4147                         cachename[i] = '_';
4148
4149         // now append the shader text itself
4150         vertstrings_list[vertstrings_count++] = vertexstring;
4151         geomstrings_list[geomstrings_count++] = geometrystring;
4152         fragstrings_list[fragstrings_count++] = fragmentstring;
4153
4154         // if any sources were NULL, clear the respective list
4155         if (!vertexstring)
4156                 vertstrings_count = 0;
4157         if (!geometrystring)
4158                 geomstrings_count = 0;
4159         if (!fragmentstring)
4160                 fragstrings_count = 0;
4161
4162         vertstring_length = 0;
4163         for (i = 0;i < vertstrings_count;i++)
4164                 vertstring_length += strlen(vertstrings_list[i]);
4165         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4166         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4167                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4168
4169         geomstring_length = 0;
4170         for (i = 0;i < geomstrings_count;i++)
4171                 geomstring_length += strlen(geomstrings_list[i]);
4172         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4173         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4174                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4175
4176         fragstring_length = 0;
4177         for (i = 0;i < fragstrings_count;i++)
4178                 fragstring_length += strlen(fragstrings_list[i]);
4179         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4180         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4181                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4182
4183         CHECKGLERROR
4184         CHECKCGERROR
4185         //vertexProfile = CG_PROFILE_ARBVP1;
4186         //fragmentProfile = CG_PROFILE_ARBFP1;
4187         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4188         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4189         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4190         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4191         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4192         CHECKGLERROR
4193
4194         // try to load the cached shader, or generate one
4195         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4196
4197         // if caching failed, do a dynamic compile for now
4198         CHECKCGERROR
4199         if (vertstring[0] && !p->vprogram)
4200                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4201         CHECKCGERROR
4202         if (fragstring[0] && !p->fprogram)
4203                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4204         CHECKCGERROR
4205
4206         // look up all the uniform variable names we care about, so we don't
4207         // have to look them up every time we set them
4208         if (p->vprogram)
4209         {
4210                 CHECKCGERROR
4211                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4212                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4213                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4214                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4215                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4216                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4217                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4218                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4219                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4220                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4221                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4222                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4223                 CHECKCGERROR
4224         }
4225         if (p->fprogram)
4226         {
4227                 CHECKCGERROR
4228                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4229                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4230                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4231                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4232                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4233                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4234                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4235                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4236                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4237                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4238                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4239                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4240                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4241                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4242                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4243                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4244                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4245                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4246                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4247                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4248                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4249                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4250                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4251                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4252                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4253                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4254                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4255                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4256                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4257                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4258                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4259                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4260                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4261                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4262                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4263                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4264                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4265                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4266                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4267                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4268                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4269                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4270                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4271                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4272                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4273                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4274                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4275                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4276                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4277                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4278                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4279                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4280                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4281                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4282                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4283                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4284                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4285                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4286                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4287                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4288                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4289                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4290                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4291                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4292                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4293                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4294                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4295                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4296                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4297                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4298                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4299                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4300                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4301                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4302                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4303                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4304                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4305                 CHECKCGERROR
4306         }
4307
4308         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4309                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4310         else
4311                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4312
4313         // free the strings
4314         if (vertstring)
4315                 Mem_Free(vertstring);
4316         if (geomstring)
4317                 Mem_Free(geomstring);
4318         if (fragstring)
4319                 Mem_Free(fragstring);
4320         if (vertexstring)
4321                 Mem_Free(vertexstring);
4322         if (geometrystring)
4323                 Mem_Free(geometrystring);
4324         if (fragmentstring)
4325                 Mem_Free(fragmentstring);
4326 }
4327
4328 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4329 {
4330         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4331         CHECKGLERROR
4332         CHECKCGERROR
4333         if (r_cg_permutation != perm)
4334         {
4335                 r_cg_permutation = perm;
4336                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4337                 {
4338                         if (!r_cg_permutation->compiled)
4339                                 R_CG_CompilePermutation(perm, mode, permutation);
4340                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4341                         {
4342                                 // remove features until we find a valid permutation
4343                                 int i;
4344                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4345                                 {
4346                                         // reduce i more quickly whenever it would not remove any bits
4347                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4348                                         if (!(permutation & j))
4349                                                 continue;
4350                                         permutation -= j;
4351                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4352                                         if (!r_cg_permutation->compiled)
4353                                                 R_CG_CompilePermutation(perm, mode, permutation);
4354                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4355                                                 break;
4356                                 }
4357                                 if (i >= SHADERPERMUTATION_COUNT)
4358                                 {
4359                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4360                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4361                                         return; // no bit left to clear, entire mode is broken
4362                                 }
4363                         }
4364                 }
4365                 CHECKGLERROR
4366                 CHECKCGERROR
4367                 if (r_cg_permutation->vprogram)
4368                 {
4369                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4370                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4371                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4372                 }
4373                 else
4374                 {
4375                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4376                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4377                 }
4378                 if (r_cg_permutation->fprogram)
4379                 {
4380                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4381                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4382                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4383                 }
4384                 else
4385                 {
4386                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4387                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4388                 }
4389         }
4390         CHECKCGERROR
4391         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4392         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4393         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4394 }
4395
4396 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4397 {
4398         cgGLSetTextureParameter(param, R_GetTexture(tex));
4399         cgGLEnableTextureParameter(param);
4400 }
4401 #endif
4402
4403 #ifdef SUPPORTD3D
4404
4405 #ifdef SUPPORTD3D
4406 #include <d3d9.h>
4407 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4408 extern D3DCAPS9 vid_d3d9caps;
4409 #endif
4410
4411 struct r_hlsl_permutation_s;
4412 typedef struct r_hlsl_permutation_s
4413 {
4414         /// hash lookup data
4415         struct r_hlsl_permutation_s *hashnext;
4416         unsigned int mode;
4417         unsigned int permutation;
4418
4419         /// indicates if we have tried compiling this permutation already
4420         qboolean compiled;
4421         /// NULL if compilation failed
4422         IDirect3DVertexShader9 *vertexshader;
4423         IDirect3DPixelShader9 *pixelshader;
4424 }
4425 r_hlsl_permutation_t;
4426
4427 typedef enum D3DVSREGISTER_e
4428 {
4429         D3DVSREGISTER_TexMatrix = 0, // float4x4
4430         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4431         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4432         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4433         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4434         D3DVSREGISTER_ModelToLight = 20, // float4x4
4435         D3DVSREGISTER_EyePosition = 24,
4436         D3DVSREGISTER_FogPlane = 25,
4437         D3DVSREGISTER_LightDir = 26,
4438         D3DVSREGISTER_LightPosition = 27,
4439 }
4440 D3DVSREGISTER_t;
4441
4442 typedef enum D3DPSREGISTER_e
4443 {
4444         D3DPSREGISTER_Alpha = 0,
4445         D3DPSREGISTER_BloomBlur_Parameters = 1,
4446         D3DPSREGISTER_ClientTime = 2,
4447         D3DPSREGISTER_Color_Ambient = 3,
4448         D3DPSREGISTER_Color_Diffuse = 4,
4449         D3DPSREGISTER_Color_Specular = 5,
4450         D3DPSREGISTER_Color_Glow = 6,
4451         D3DPSREGISTER_Color_Pants = 7,
4452         D3DPSREGISTER_Color_Shirt = 8,
4453         D3DPSREGISTER_DeferredColor_Ambient = 9,
4454         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4455         D3DPSREGISTER_DeferredColor_Specular = 11,
4456         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4457         D3DPSREGISTER_DeferredMod_Specular = 13,
4458         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4459         D3DPSREGISTER_EyePosition = 15, // unused
4460         D3DPSREGISTER_FogColor = 16,
4461         D3DPSREGISTER_FogHeightFade = 17,
4462         D3DPSREGISTER_FogPlane = 18,
4463         D3DPSREGISTER_FogPlaneViewDist = 19,
4464         D3DPSREGISTER_FogRangeRecip = 20,
4465         D3DPSREGISTER_LightColor = 21,
4466         D3DPSREGISTER_LightDir = 22, // unused
4467         D3DPSREGISTER_LightPosition = 23,
4468         D3DPSREGISTER_OffsetMapping_Scale = 24,
4469         D3DPSREGISTER_PixelSize = 25,
4470         D3DPSREGISTER_ReflectColor = 26,
4471         D3DPSREGISTER_ReflectFactor = 27,
4472         D3DPSREGISTER_ReflectOffset = 28,
4473         D3DPSREGISTER_RefractColor = 29,
4474         D3DPSREGISTER_Saturation = 30,
4475         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4476         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4477         D3DPSREGISTER_ScreenToDepth = 33,
4478         D3DPSREGISTER_ShadowMap_Parameters = 34,
4479         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4480         D3DPSREGISTER_SpecularPower = 36,
4481         D3DPSREGISTER_UserVec1 = 37,
4482         D3DPSREGISTER_UserVec2 = 38,
4483         D3DPSREGISTER_UserVec3 = 39,
4484         D3DPSREGISTER_UserVec4 = 40,
4485         D3DPSREGISTER_ViewTintColor = 41,
4486         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4487         D3DPSREGISTER_BloomColorSubtract = 43,
4488         D3DPSREGISTER_ViewToLight = 44, // float4x4
4489         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4490         // next at 52
4491 }
4492 D3DPSREGISTER_t;
4493
4494 /// information about each possible shader permutation
4495 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4496 /// currently selected permutation
4497 r_hlsl_permutation_t *r_hlsl_permutation;
4498 /// storage for permutations linked in the hash table
4499 memexpandablearray_t r_hlsl_permutationarray;
4500
4501 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4502 {
4503         //unsigned int hashdepth = 0;
4504         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4505         r_hlsl_permutation_t *p;
4506         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4507         {
4508                 if (p->mode == mode && p->permutation == permutation)
4509                 {
4510                         //if (hashdepth > 10)
4511                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4512                         return p;
4513                 }
4514                 //hashdepth++;
4515         }
4516         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4517         p->mode = mode;
4518         p->permutation = permutation;
4519         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4520         r_hlsl_permutationhash[mode][hashindex] = p;
4521         //if (hashdepth > 10)
4522         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4523         return p;
4524 }
4525
4526 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4527 {
4528         char *shaderstring;
4529         if (!filename || !filename[0])
4530                 return NULL;
4531         if (!strcmp(filename, "hlsl/default.hlsl"))
4532         {
4533                 if (!hlslshaderstring)
4534                 {
4535                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4536                         if (hlslshaderstring)
4537                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4538                         else
4539                                 hlslshaderstring = (char *)builtincgshaderstring;
4540                 }
4541                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4542                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4543                 return shaderstring;
4544         }
4545         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4546         if (shaderstring)
4547         {
4548                 if (printfromdisknotice)
4549                         Con_DPrintf("from disk %s... ", filename);
4550                 return shaderstring;
4551         }
4552         return shaderstring;
4553 }
4554
4555 #include <d3dx9.h>
4556 //#include <d3dx9shader.h>
4557 //#include <d3dx9mesh.h>
4558
4559 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4560 {
4561         DWORD *vsbin = NULL;
4562         DWORD *psbin = NULL;
4563         fs_offset_t vsbinsize;
4564         fs_offset_t psbinsize;
4565 //      IDirect3DVertexShader9 *vs = NULL;
4566 //      IDirect3DPixelShader9 *ps = NULL;
4567         ID3DXBuffer *vslog = NULL;
4568         ID3DXBuffer *vsbuffer = NULL;
4569         ID3DXConstantTable *vsconstanttable = NULL;
4570         ID3DXBuffer *pslog = NULL;
4571         ID3DXBuffer *psbuffer = NULL;
4572         ID3DXConstantTable *psconstanttable = NULL;
4573         int vsresult = 0;
4574         int psresult = 0;
4575         char temp[MAX_INPUTLINE];
4576         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4577         qboolean debugshader = gl_paranoid.integer != 0;
4578         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4579         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4580         if (!debugshader)
4581         {
4582                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4583                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4584         }
4585         if ((!vsbin && vertstring) || (!psbin && fragstring))
4586         {
4587                 const char* dllnames_d3dx9 [] =
4588                 {
4589                         "d3dx9_43.dll",
4590                         "d3dx9_42.dll",
4591                         "d3dx9_41.dll",
4592                         "d3dx9_40.dll",
4593                         "d3dx9_39.dll",
4594                         "d3dx9_38.dll",
4595                         "d3dx9_37.dll",
4596                         "d3dx9_36.dll",
4597                         "d3dx9_35.dll",
4598                         "d3dx9_34.dll",
4599                         "d3dx9_33.dll",
4600                         "d3dx9_32.dll",
4601                         "d3dx9_31.dll",
4602                         "d3dx9_30.dll",
4603                         "d3dx9_29.dll",
4604                         "d3dx9_28.dll",
4605                         "d3dx9_27.dll",
4606                         "d3dx9_26.dll",
4607                         "d3dx9_25.dll",
4608                         "d3dx9_24.dll",
4609                         NULL
4610                 };
4611                 dllhandle_t d3dx9_dll = NULL;
4612                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4613                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4614                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4615                 dllfunction_t d3dx9_dllfuncs[] =
4616                 {
4617                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4618                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4619                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4620                         {NULL, NULL}
4621                 };
4622                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4623                 {
4624                         DWORD shaderflags = 0;
4625                         if (debugshader)
4626                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4627                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4628                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4629                         if (vertstring && vertstring[0])
4630                         {
4631                                 if (debugshader)
4632                                 {
4633 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4634 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4635                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4636                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4637                                 }
4638                                 else
4639                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4640                                 if (vsbuffer)
4641                                 {
4642                                         vsbinsize = vsbuffer->GetBufferSize();
4643                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4644                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4645                                         vsbuffer->Release();
4646                                 }
4647                                 if (vslog)
4648                                 {
4649                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4650                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4651                                         vslog->Release();
4652                                 }
4653                         }
4654                         if (fragstring && fragstring[0])
4655                         {
4656                                 if (debugshader)
4657                                 {
4658 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4659 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4660                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4661                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4662                                 }
4663                                 else
4664                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4665                                 if (psbuffer)
4666                                 {
4667                                         psbinsize = psbuffer->GetBufferSize();
4668                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4669                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4670                                         psbuffer->Release();
4671                                 }
4672                                 if (pslog)
4673                                 {
4674                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4675                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4676                                         pslog->Release();
4677                                 }
4678                         }
4679                         Sys_UnloadLibrary(&d3dx9_dll);
4680                 }
4681                 else
4682                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4683         }
4684         if (vsbin && psbin)
4685         {
4686                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4687                 if (FAILED(vsresult))
4688                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4689                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4690                 if (FAILED(psresult))
4691                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4692         }
4693         // free the shader data
4694         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4695         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4696 }
4697
4698 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4699 {
4700         int i;
4701         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4702         int vertstring_length = 0;
4703         int geomstring_length = 0;
4704         int fragstring_length = 0;
4705         char *t;
4706         char *vertexstring, *geometrystring, *fragmentstring;
4707         char *vertstring, *geomstring, *fragstring;
4708         char permutationname[256];
4709         char cachename[256];
4710
4711         if (p->compiled)
4712                 return;
4713         p->compiled = true;
4714         p->vertexshader = NULL;
4715         p->pixelshader = NULL;
4716
4717         permutationname[0] = 0;
4718         cachename[0] = 0;
4719         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4720         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4721         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4722
4723         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4724         strlcat(cachename, "hlsl/", sizeof(cachename));
4725
4726         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4727         vertstrings_count = 0;
4728         geomstrings_count = 0;
4729         fragstrings_count = 0;
4730         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4731         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4732         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4733
4734         // the first pretext is which type of shader to compile as
4735         // (later these will all be bound together as a program object)
4736         vertstrings_count = 0;
4737         geomstrings_count = 0;
4738         fragstrings_count = 0;
4739         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4740         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4741         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4742
4743         // the second pretext is the mode (for example a light source)
4744         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4745         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4746         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4747         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4748         strlcat(cachename, modeinfo->name, sizeof(cachename));
4749
4750         // now add all the permutation pretexts
4751         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4752         {
4753                 if (permutation & (1<<i))
4754                 {
4755                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4756                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4757                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4758                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4759                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4760                 }
4761                 else
4762                 {
4763                         // keep line numbers correct
4764                         vertstrings_list[vertstrings_count++] = "\n";
4765                         geomstrings_list[geomstrings_count++] = "\n";
4766                         fragstrings_list[fragstrings_count++] = "\n";
4767                 }
4768         }
4769
4770         // add static parms
4771         R_CompileShader_AddStaticParms(mode, permutation);
4772
4773         // replace spaces in the cachename with _ characters
4774         for (i = 0;cachename[i];i++)
4775                 if (cachename[i] == ' ')
4776                         cachename[i] = '_';
4777
4778         // now append the shader text itself
4779         vertstrings_list[vertstrings_count++] = vertexstring;
4780         geomstrings_list[geomstrings_count++] = geometrystring;
4781         fragstrings_list[fragstrings_count++] = fragmentstring;
4782
4783         // if any sources were NULL, clear the respective list
4784         if (!vertexstring)
4785                 vertstrings_count = 0;
4786         if (!geometrystring)
4787                 geomstrings_count = 0;
4788         if (!fragmentstring)
4789                 fragstrings_count = 0;
4790
4791         vertstring_length = 0;
4792         for (i = 0;i < vertstrings_count;i++)
4793                 vertstring_length += strlen(vertstrings_list[i]);
4794         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4795         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4796                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4797
4798         geomstring_length = 0;
4799         for (i = 0;i < geomstrings_count;i++)
4800                 geomstring_length += strlen(geomstrings_list[i]);
4801         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4802         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4803                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4804
4805         fragstring_length = 0;
4806         for (i = 0;i < fragstrings_count;i++)
4807                 fragstring_length += strlen(fragstrings_list[i]);
4808         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4809         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4810                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4811
4812         // try to load the cached shader, or generate one
4813         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4814
4815         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4816                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4817         else
4818                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4819
4820         // free the strings
4821         if (vertstring)
4822                 Mem_Free(vertstring);
4823         if (geomstring)
4824                 Mem_Free(geomstring);
4825         if (fragstring)
4826                 Mem_Free(fragstring);
4827         if (vertexstring)
4828                 Mem_Free(vertexstring);
4829         if (geometrystring)
4830                 Mem_Free(geometrystring);
4831         if (fragmentstring)
4832                 Mem_Free(fragmentstring);
4833 }
4834
4835 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4836 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4837 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);}
4838 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);}
4839 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);}
4840 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);}
4841
4842 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4843 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4844 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);}
4845 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);}
4846 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);}
4847 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);}
4848
4849 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4850 {
4851         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4852         if (r_hlsl_permutation != perm)
4853         {
4854                 r_hlsl_permutation = perm;
4855                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4856                 {
4857                         if (!r_hlsl_permutation->compiled)
4858                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4859                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4860                         {
4861                                 // remove features until we find a valid permutation
4862                                 int i;
4863                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4864                                 {
4865                                         // reduce i more quickly whenever it would not remove any bits
4866                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4867                                         if (!(permutation & j))
4868                                                 continue;
4869                                         permutation -= j;
4870                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4871                                         if (!r_hlsl_permutation->compiled)
4872                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4873                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4874                                                 break;
4875                                 }
4876                                 if (i >= SHADERPERMUTATION_COUNT)
4877                                 {
4878                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4879                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4880                                         return; // no bit left to clear, entire mode is broken
4881                                 }
4882                         }
4883                 }
4884                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4885                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4886         }
4887         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4888         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4889         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4890 }
4891 #endif
4892
4893 void R_GLSL_Restart_f(void)
4894 {
4895         unsigned int i, limit;
4896         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4897                 Mem_Free(glslshaderstring);
4898         glslshaderstring = NULL;
4899         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4900                 Mem_Free(cgshaderstring);
4901         cgshaderstring = NULL;
4902         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4903                 Mem_Free(hlslshaderstring);
4904         hlslshaderstring = NULL;
4905         switch(vid.renderpath)
4906         {
4907         case RENDERPATH_D3D9:
4908 #ifdef SUPPORTD3D
4909                 {
4910                         r_hlsl_permutation_t *p;
4911                         r_hlsl_permutation = NULL;
4912 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4913 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4914 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4915 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4916                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4917                         for (i = 0;i < limit;i++)
4918                         {
4919                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4920                                 {
4921                                         if (p->vertexshader)
4922                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4923                                         if (p->pixelshader)
4924                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4925                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4926                                 }
4927                         }
4928                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4929                 }
4930 #endif
4931                 break;
4932         case RENDERPATH_D3D10:
4933                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4934                 break;
4935         case RENDERPATH_D3D11:
4936                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4937                 break;
4938         case RENDERPATH_GL20:
4939                 {
4940                         r_glsl_permutation_t *p;
4941                         r_glsl_permutation = NULL;
4942                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4943                         for (i = 0;i < limit;i++)
4944                         {
4945                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4946                                 {
4947                                         GL_Backend_FreeProgram(p->program);
4948                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4949                                 }
4950                         }
4951                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4952                 }
4953                 break;
4954         case RENDERPATH_CGGL:
4955 #ifdef SUPPORTCG
4956                 {
4957                         r_cg_permutation_t *p;
4958                         r_cg_permutation = NULL;
4959                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4960                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4961                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4962                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4963                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4964                         for (i = 0;i < limit;i++)
4965                         {
4966                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4967                                 {
4968                                         if (p->vprogram)
4969                                                 cgDestroyProgram(p->vprogram);
4970                                         if (p->fprogram)
4971                                                 cgDestroyProgram(p->fprogram);
4972                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4973                                 }
4974                         }
4975                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4976                 }
4977 #endif
4978                 break;
4979         case RENDERPATH_GL13:
4980         case RENDERPATH_GL11:
4981                 break;
4982         }
4983 }
4984
4985 void R_GLSL_DumpShader_f(void)
4986 {
4987         int i;
4988         qfile_t *file;
4989
4990         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4991         if (file)
4992         {
4993                 FS_Print(file, "/* The engine may define the following macros:\n");
4994                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4995                 for (i = 0;i < SHADERMODE_COUNT;i++)
4996                         FS_Print(file, glslshadermodeinfo[i].pretext);
4997                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4998                         FS_Print(file, shaderpermutationinfo[i].pretext);
4999                 FS_Print(file, "*/\n");
5000                 FS_Print(file, builtinshaderstring);
5001                 FS_Close(file);
5002                 Con_Printf("glsl/default.glsl written\n");
5003         }
5004         else
5005                 Con_Printf("failed to write to glsl/default.glsl\n");
5006
5007 #ifdef SUPPORTCG
5008         file = FS_OpenRealFile("cg/default.cg", "w", false);
5009         if (file)
5010         {
5011                 FS_Print(file, "/* The engine may define the following macros:\n");
5012                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5013                 for (i = 0;i < SHADERMODE_COUNT;i++)
5014                         FS_Print(file, cgshadermodeinfo[i].pretext);
5015                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5016                         FS_Print(file, shaderpermutationinfo[i].pretext);
5017                 FS_Print(file, "*/\n");
5018                 FS_Print(file, builtincgshaderstring);
5019                 FS_Close(file);
5020                 Con_Printf("cg/default.cg written\n");
5021         }
5022         else
5023                 Con_Printf("failed to write to cg/default.cg\n");
5024 #endif
5025
5026 #ifdef SUPPORTD3D
5027         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5028         if (file)
5029         {
5030                 FS_Print(file, "/* The engine may define the following macros:\n");
5031                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5032                 for (i = 0;i < SHADERMODE_COUNT;i++)
5033                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5034                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5035                         FS_Print(file, shaderpermutationinfo[i].pretext);
5036                 FS_Print(file, "*/\n");
5037                 FS_Print(file, builtincgshaderstring);
5038                 FS_Close(file);
5039                 Con_Printf("hlsl/default.hlsl written\n");
5040         }
5041         else
5042                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5043 #endif
5044 }
5045
5046 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5047 {
5048         if (!second)
5049                 texturemode = GL_MODULATE;
5050         switch (vid.renderpath)
5051         {
5052         case RENDERPATH_D3D9:
5053 #ifdef SUPPORTD3D
5054                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5055                 R_Mesh_TexBind(GL20TU_FIRST , first );
5056                 R_Mesh_TexBind(GL20TU_SECOND, second);
5057 #endif
5058                 break;
5059         case RENDERPATH_D3D10:
5060                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5061                 break;
5062         case RENDERPATH_D3D11:
5063                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5064                 break;
5065         case RENDERPATH_GL20:
5066                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5067                 R_Mesh_TexBind(GL20TU_FIRST , first );
5068                 R_Mesh_TexBind(GL20TU_SECOND, second);
5069                 break;
5070         case RENDERPATH_CGGL:
5071 #ifdef SUPPORTCG
5072                 CHECKCGERROR
5073                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5074                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5075                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5076 #endif
5077                 break;
5078         case RENDERPATH_GL13:
5079                 R_Mesh_TexBind(0, first );
5080                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5081                 R_Mesh_TexBind(1, second);
5082                 if (second)
5083                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5084                 break;
5085         case RENDERPATH_GL11:
5086                 R_Mesh_TexBind(0, first );
5087                 break;
5088         }
5089 }
5090
5091 void R_SetupShader_DepthOrShadow(void)
5092 {
5093         switch (vid.renderpath)
5094         {
5095         case RENDERPATH_D3D9:
5096 #ifdef SUPPORTD3D
5097                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5098 #endif
5099                 break;
5100         case RENDERPATH_D3D10:
5101                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5102                 break;
5103         case RENDERPATH_D3D11:
5104                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5105                 break;
5106         case RENDERPATH_GL20:
5107                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5108                 break;
5109         case RENDERPATH_CGGL:
5110 #ifdef SUPPORTCG
5111                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5112 #endif
5113                 break;
5114         case RENDERPATH_GL13:
5115                 R_Mesh_TexBind(0, 0);
5116                 R_Mesh_TexBind(1, 0);
5117                 break;
5118         case RENDERPATH_GL11:
5119                 R_Mesh_TexBind(0, 0);
5120                 break;
5121         }
5122 }
5123
5124 void R_SetupShader_ShowDepth(void)
5125 {
5126         switch (vid.renderpath)
5127         {
5128         case RENDERPATH_D3D9:
5129 #ifdef SUPPORTHLSL
5130                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5131 #endif
5132                 break;
5133         case RENDERPATH_D3D10:
5134                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5135                 break;
5136         case RENDERPATH_D3D11:
5137                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5138                 break;
5139         case RENDERPATH_GL20:
5140                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5141                 break;
5142         case RENDERPATH_CGGL:
5143 #ifdef SUPPORTCG
5144                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5145 #endif
5146                 break;
5147         case RENDERPATH_GL13:
5148                 break;
5149         case RENDERPATH_GL11:
5150                 break;
5151         }
5152 }
5153
5154 extern qboolean r_shadow_usingdeferredprepass;
5155 extern cvar_t r_shadow_deferred_8bitrange;
5156 extern rtexture_t *r_shadow_attenuationgradienttexture;
5157 extern rtexture_t *r_shadow_attenuation2dtexture;
5158 extern rtexture_t *r_shadow_attenuation3dtexture;
5159 extern qboolean r_shadow_usingshadowmap2d;
5160 extern qboolean r_shadow_usingshadowmaportho;
5161 extern float r_shadow_shadowmap_texturescale[2];
5162 extern float r_shadow_shadowmap_parameters[4];
5163 extern qboolean r_shadow_shadowmapvsdct;
5164 extern qboolean r_shadow_shadowmapsampler;
5165 extern int r_shadow_shadowmappcf;
5166 extern rtexture_t *r_shadow_shadowmap2dtexture;
5167 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5168 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5169 extern matrix4x4_t r_shadow_shadowmapmatrix;
5170 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5171 extern int r_shadow_prepass_width;
5172 extern int r_shadow_prepass_height;
5173 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5174 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5175 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5176 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5177 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5178 extern cvar_t gl_mesh_separatearrays;
5179 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5180 {
5181         // a blendfunc allows colormod if:
5182         // a) it can never keep the destination pixel invariant, or
5183         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5184         // this is to prevent unintended side effects from colormod
5185
5186         // in formulas:
5187         // IF there is a (s, sa) for which for all (d, da),
5188         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5189         // THEN, for this (s, sa) and all (colormod, d, da):
5190         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5191         // OBVIOUSLY, this means that
5192         //   s*colormod * src(s*colormod, d, sa, da) = 0
5193         //   dst(s*colormod, d, sa, da)              = 1
5194
5195         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5196
5197         // main condition to leave dst color invariant:
5198         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5199         //   src == GL_ZERO:
5200         //     s * 0 + d * dst(s, d, sa, da) == d
5201         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5202         //       => colormod is a problem for GL_SRC_COLOR only
5203         //   src == GL_ONE:
5204         //     s + d * dst(s, d, sa, da) == d
5205         //       => s == 0
5206         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5207         //       => colormod is never problematic for these
5208         //   src == GL_SRC_COLOR:
5209         //     s*s + d * dst(s, d, sa, da) == d
5210         //       => s == 0
5211         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5212         //       => colormod is never problematic for these
5213         //   src == GL_ONE_MINUS_SRC_COLOR:
5214         //     s*(1-s) + d * dst(s, d, sa, da) == d
5215         //       => s == 0 or s == 1
5216         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5217         //       => colormod is a problem for GL_SRC_COLOR only
5218         //   src == GL_DST_COLOR
5219         //     s*d + d * dst(s, d, sa, da) == d
5220         //       => s == 1
5221         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5222         //       => colormod is always a problem
5223         //     or
5224         //       => s == 0
5225         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5226         //       => colormod is never problematic for these
5227         //       => BUT, we do not know s! We must assume it is problematic
5228         //       then... except in GL_ONE case, where we know all invariant
5229         //       cases are fine
5230         //   src == GL_ONE_MINUS_DST_COLOR
5231         //     s*(1-d) + d * dst(s, d, sa, da) == d
5232         //       => s == 0 (1-d is impossible to handle for our desired result)
5233         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5234         //       => colormod is never problematic for these
5235         //   src == GL_SRC_ALPHA
5236         //     s*sa + d * dst(s, d, sa, da) == d
5237         //       => s == 0, or sa == 0
5238         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5239         //       => colormod breaks in the case GL_SRC_COLOR only
5240         //   src == GL_ONE_MINUS_SRC_ALPHA
5241         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5242         //       => s == 0, or sa == 1
5243         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5244         //       => colormod breaks in the case GL_SRC_COLOR only
5245         //   src == GL_DST_ALPHA
5246         //     s*da + d * dst(s, d, sa, da) == d
5247         //       => s == 0
5248         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5249         //       => colormod is never problematic for these
5250
5251         switch(src)
5252         {
5253                 case GL_ZERO:
5254                 case GL_ONE_MINUS_SRC_COLOR:
5255                 case GL_SRC_ALPHA:
5256                 case GL_ONE_MINUS_SRC_ALPHA:
5257                         if(dst == GL_SRC_COLOR)
5258                                 return false;
5259                         return true;
5260                 case GL_ONE:
5261                 case GL_SRC_COLOR:
5262                 case GL_ONE_MINUS_DST_COLOR:
5263                 case GL_DST_ALPHA:
5264                 case GL_ONE_MINUS_DST_ALPHA:
5265                         return true;
5266                 case GL_DST_COLOR:
5267                         if(dst == GL_ONE)
5268                                 return true;
5269                         return false;
5270                 default:
5271                         return false;
5272         }
5273 }
5274 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)
5275 {
5276         // select a permutation of the lighting shader appropriate to this
5277         // combination of texture, entity, light source, and fogging, only use the
5278         // minimum features necessary to avoid wasting rendering time in the
5279         // fragment shader on features that are not being used
5280         unsigned int permutation = 0;
5281         unsigned int mode = 0;
5282         qboolean allow_colormod;
5283         static float dummy_colormod[3] = {1, 1, 1};
5284         float *colormod = rsurface.colormod;
5285         float m16f[16];
5286         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5287         if (rsurfacepass == RSURFPASS_BACKGROUND)
5288         {
5289                 // distorted background
5290                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5291                 {
5292                         mode = SHADERMODE_WATER;
5293                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5294                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5295                 }
5296                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5297                 {
5298                         mode = SHADERMODE_REFRACTION;
5299                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5300                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5301                 }
5302                 else
5303                 {
5304                         mode = SHADERMODE_GENERIC;
5305                         permutation |= SHADERPERMUTATION_DIFFUSE;
5306                         GL_BlendFunc(GL_ONE, GL_ZERO);
5307                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5308                 }
5309                 GL_AlphaTest(false);
5310         }
5311         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5312         {
5313                 if (r_glsl_offsetmapping.integer)
5314                 {
5315                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5316                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5317                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5318                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5319                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5320                         {
5321                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5322                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5323                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5324                         }
5325                 }
5326                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5327                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5328                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5329                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5330                 // normalmap (deferred prepass), may use alpha test on diffuse
5331                 mode = SHADERMODE_DEFERREDGEOMETRY;
5332                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5333                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5334                 GL_AlphaTest(false);
5335                 GL_BlendFunc(GL_ONE, GL_ZERO);
5336                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5337         }
5338         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5339         {
5340                 if (r_glsl_offsetmapping.integer)
5341                 {
5342                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5343                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5344                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5345                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5346                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5347                         {
5348                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5349                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5350                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5351                         }
5352                 }
5353                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5354                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5355                 // light source
5356                 mode = SHADERMODE_LIGHTSOURCE;
5357                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5358                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5359                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5360                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5361                 if (diffusescale > 0)
5362                         permutation |= SHADERPERMUTATION_DIFFUSE;
5363                 if (specularscale > 0)
5364                 {
5365                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5366                         if (r_shadow_glossexact.integer)
5367                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5368                 }
5369                 if (r_refdef.fogenabled)
5370                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5371                 if (rsurface.texture->colormapping)
5372                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5373                 if (r_shadow_usingshadowmap2d)
5374                 {
5375                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5376                         if(r_shadow_shadowmapvsdct)
5377                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5378
5379                         if (r_shadow_shadowmapsampler)
5380                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5381                         if (r_shadow_shadowmappcf > 1)
5382                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5383                         else if (r_shadow_shadowmappcf)
5384                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5385                 }
5386                 if (rsurface.texture->reflectmasktexture)
5387                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5388                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5389                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5390                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5391         }
5392         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5393         {
5394                 if (r_glsl_offsetmapping.integer)
5395                 {
5396                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5397                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5398                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5399                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5400                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5401                         {
5402                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5403                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5404                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5405                         }
5406                 }
5407                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5408                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5409                 // unshaded geometry (fullbright or ambient model lighting)
5410                 mode = SHADERMODE_FLATCOLOR;
5411                 ambientscale = diffusescale = specularscale = 0;
5412                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5413                         permutation |= SHADERPERMUTATION_GLOW;
5414                 if (r_refdef.fogenabled)
5415                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5416                 if (rsurface.texture->colormapping)
5417                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5418                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5419                 {
5420                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5421                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5422
5423                         if (r_shadow_shadowmapsampler)
5424                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5425                         if (r_shadow_shadowmappcf > 1)
5426                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5427                         else if (r_shadow_shadowmappcf)
5428                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5429                 }
5430                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5431                         permutation |= SHADERPERMUTATION_REFLECTION;
5432                 if (rsurface.texture->reflectmasktexture)
5433                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5434                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5435                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5436                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5437         }
5438         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5439         {
5440                 if (r_glsl_offsetmapping.integer)
5441                 {
5442                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5443                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5444                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5445                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5446                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5447                         {
5448                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5449                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5450                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5451                         }
5452                 }
5453                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5454                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5455                 // directional model lighting
5456                 mode = SHADERMODE_LIGHTDIRECTION;
5457                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5458                         permutation |= SHADERPERMUTATION_GLOW;
5459                 permutation |= SHADERPERMUTATION_DIFFUSE;
5460                 if (specularscale > 0)
5461                 {
5462                         permutation |= SHADERPERMUTATION_SPECULAR;
5463                         if (r_shadow_glossexact.integer)
5464                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5465                 }
5466                 if (r_refdef.fogenabled)
5467                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5468                 if (rsurface.texture->colormapping)
5469                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5470                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5471                 {
5472                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5473                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5474
5475                         if (r_shadow_shadowmapsampler)
5476                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5477                         if (r_shadow_shadowmappcf > 1)
5478                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5479                         else if (r_shadow_shadowmappcf)
5480                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5481                 }
5482                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5483                         permutation |= SHADERPERMUTATION_REFLECTION;
5484                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5485                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5486                 if (rsurface.texture->reflectmasktexture)
5487                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5488                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5489                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5490                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5491         }
5492         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5493         {
5494                 if (r_glsl_offsetmapping.integer)
5495                 {
5496                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5497                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5498                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5499                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5500                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5501                         {
5502                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5503                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5504                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5505                         }
5506                 }
5507                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5508                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5509                 // ambient model lighting
5510                 mode = SHADERMODE_LIGHTDIRECTION;
5511                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5512                         permutation |= SHADERPERMUTATION_GLOW;
5513                 if (r_refdef.fogenabled)
5514                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5515                 if (rsurface.texture->colormapping)
5516                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5517                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5518                 {
5519                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5520                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5521
5522                         if (r_shadow_shadowmapsampler)
5523                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5524                         if (r_shadow_shadowmappcf > 1)
5525                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5526                         else if (r_shadow_shadowmappcf)
5527                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5528                 }
5529                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5530                         permutation |= SHADERPERMUTATION_REFLECTION;
5531                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5532                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5533                 if (rsurface.texture->reflectmasktexture)
5534                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5535                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5536                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5537                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5538         }
5539         else
5540         {
5541                 if (r_glsl_offsetmapping.integer)
5542                 {
5543                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5544                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5545                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5546                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5547                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5548                         {
5549                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5550                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5551                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5552                         }
5553                 }
5554                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5555                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5556                 // lightmapped wall
5557                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5558                         permutation |= SHADERPERMUTATION_GLOW;
5559                 if (r_refdef.fogenabled)
5560                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5561                 if (rsurface.texture->colormapping)
5562                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5563                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5564                 {
5565                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5566                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5567
5568                         if (r_shadow_shadowmapsampler)
5569                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5570                         if (r_shadow_shadowmappcf > 1)
5571                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5572                         else if (r_shadow_shadowmappcf)
5573                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5574                 }
5575                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5576                         permutation |= SHADERPERMUTATION_REFLECTION;
5577                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5578                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5579                 if (rsurface.texture->reflectmasktexture)
5580                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5581                 if (FAKELIGHT_ENABLED)
5582                 {
5583                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5584                         mode = SHADERMODE_FAKELIGHT;
5585                         permutation |= SHADERPERMUTATION_DIFFUSE;
5586                         if (specularscale > 0)
5587                         {
5588                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5589                                 if (r_shadow_glossexact.integer)
5590                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5591                         }
5592                 }
5593                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5594                 {
5595                         // deluxemapping (light direction texture)
5596                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5597                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5598                         else
5599                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5600                         permutation |= SHADERPERMUTATION_DIFFUSE;
5601                         if (specularscale > 0)
5602                         {
5603                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5604                                 if (r_shadow_glossexact.integer)
5605                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5606                         }
5607                 }
5608                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5609                 {
5610                         // fake deluxemapping (uniform light direction in tangentspace)
5611                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5612                         permutation |= SHADERPERMUTATION_DIFFUSE;
5613                         if (specularscale > 0)
5614                         {
5615                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5616                                 if (r_shadow_glossexact.integer)
5617                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5618                         }
5619                 }
5620                 else if (rsurface.uselightmaptexture)
5621                 {
5622                         // ordinary lightmapping (q1bsp, q3bsp)
5623                         mode = SHADERMODE_LIGHTMAP;
5624                 }
5625                 else
5626                 {
5627                         // ordinary vertex coloring (q3bsp)
5628                         mode = SHADERMODE_VERTEXCOLOR;
5629                 }
5630                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5631                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5632                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5633         }
5634         if(!allow_colormod)
5635                 colormod = dummy_colormod;
5636         switch(vid.renderpath)
5637         {
5638         case RENDERPATH_D3D9:
5639 #ifdef SUPPORTD3D
5640                 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);
5641                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5642                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5643                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5644                 if (mode == SHADERMODE_LIGHTSOURCE)
5645                 {
5646                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5647                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5648                 }
5649                 else
5650                 {
5651                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5652                         {
5653                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5654                         }
5655                 }
5656                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5657                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5658                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5659                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5660                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5661
5662                 if (mode == SHADERMODE_LIGHTSOURCE)
5663                 {
5664                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5665                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5666                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5667                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5668                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5669
5670                         // additive passes are only darkened by fog, not tinted
5671                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5672                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5673                 }
5674                 else
5675                 {
5676                         if (mode == SHADERMODE_FLATCOLOR)
5677                         {
5678                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5679                         }
5680                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5681                         {
5682                                 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]);
5683                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5684                                 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);
5685                                 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);
5686                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5687                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5688                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5689                         }
5690                         else
5691                         {
5692                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5693                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5694                                 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);
5695                                 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);
5696                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5697                         }
5698                         // additive passes are only darkened by fog, not tinted
5699                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5700                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5701                         else
5702                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5703                         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);
5704                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5705                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5706                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5707                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5708                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5709                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5710                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5711                 }
5712                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5713                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5714                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5715                 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));
5716                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5717                 if (rsurface.texture->pantstexture)
5718                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5719                 else
5720                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5721                 if (rsurface.texture->shirttexture)
5722                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5723                 else
5724                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5725                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5726                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5727                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5728                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5729                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5730                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5731                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5732
5733                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5734                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5735                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5736                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5737                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5738                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5739                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5740                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5741                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5742                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5743                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5744                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5745                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5746                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5747                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5748                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5749                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5750                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5751                 {
5752                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5753                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5754                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5755                 }
5756                 else
5757                 {
5758                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5759                 }
5760 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5761 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5762                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5763                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5764                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5765                 {
5766                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5767                         if (rsurface.rtlight)
5768                         {
5769                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5770                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5771                         }
5772                 }
5773 #endif
5774                 break;
5775         case RENDERPATH_D3D10:
5776                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5777                 break;
5778         case RENDERPATH_D3D11:
5779                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5780                 break;
5781         case RENDERPATH_GL20:
5782                 if (gl_mesh_separatearrays.integer)
5783                 {
5784                         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);
5785                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5786                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5787                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5788                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5789                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5790                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5791                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5792                 }
5793                 else
5794                 {
5795                         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);
5796                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5797                 }
5798                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5799                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5800                 if (mode == SHADERMODE_LIGHTSOURCE)
5801                 {
5802                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5803                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5804                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5805                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5806                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5807                         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);
5808         
5809                         // additive passes are only darkened by fog, not tinted
5810                         if (r_glsl_permutation->loc_FogColor >= 0)
5811                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5812                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5813                 }
5814                 else
5815                 {
5816                         if (mode == SHADERMODE_FLATCOLOR)
5817                         {
5818                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5819                         }
5820                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5821                         {
5822                                 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) * 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]);
5823                                 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]);
5824                                 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);
5825                                 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);
5826                                 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);
5827                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5828                                 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]);
5829                         }
5830                         else
5831                         {
5832                                 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]);
5833                                 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]);
5834                                 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);
5835                                 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);
5836                                 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);
5837                         }
5838                         // additive passes are only darkened by fog, not tinted
5839                         if (r_glsl_permutation->loc_FogColor >= 0)
5840                         {
5841                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5842                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5843                                 else
5844                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5845                         }
5846                         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);
5847                         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]);
5848                         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]);
5849                         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]);
5850                         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]);
5851                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5852                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5853                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5854                 }
5855                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5856                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5857                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5858                 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]);
5859                 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]);
5860
5861                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5862                 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));
5863                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5864                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5865                 {
5866                         if (rsurface.texture->pantstexture)
5867                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5868                         else
5869                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5870                 }
5871                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5872                 {
5873                         if (rsurface.texture->shirttexture)
5874                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5875                         else
5876                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5877                 }
5878                 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]);
5879                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5880                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5881                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5882                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5883                 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]);
5884                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5885
5886         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5887         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5888         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5889                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5890                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5891                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5892                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5893                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5894                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5895                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5896                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5897                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5898                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5899                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5900                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5901                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5902                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5903                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5904                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5905                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5906                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5907                 {
5908                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5909                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5910                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5911                 }
5912                 else
5913                 {
5914                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5915                 }
5916 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5917 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5918                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5919                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5920                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5921                 {
5922                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5923                         if (rsurface.rtlight)
5924                         {
5925                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5926                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5927                         }
5928                 }
5929                 CHECKGLERROR
5930                 break;
5931         case RENDERPATH_CGGL:
5932 #ifdef SUPPORTCG
5933                 if (gl_mesh_separatearrays.integer)
5934                 {
5935                         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);
5936                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5937                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5938                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5939                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5940                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5941                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5942                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5943                 }
5944                 else
5945                 {
5946                         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);
5947                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5948                 }
5949                 R_SetupShader_SetPermutationCG(mode, permutation);
5950                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5951                 if (mode == SHADERMODE_LIGHTSOURCE)
5952                 {
5953                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5954                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5955                 }
5956                 else
5957                 {
5958                         if (mode == SHADERMODE_LIGHTDIRECTION)
5959                         {
5960                                 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
5961                         }
5962                 }
5963                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5964                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5965                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5966                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5967                 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
5968                 CHECKGLERROR
5969
5970                 if (mode == SHADERMODE_LIGHTSOURCE)
5971                 {
5972                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5973                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5974                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5975                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5976                         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
5977
5978                         // additive passes are only darkened by fog, not tinted
5979                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5980                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5981                 }
5982                 else
5983                 {
5984                         if (mode == SHADERMODE_FLATCOLOR)
5985                         {
5986                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5987                         }
5988                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5989                         {
5990                                 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
5991                                 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
5992                                 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
5993                                 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
5994                                 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
5995                                 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
5996                                 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
5997                         }
5998                         else
5999                         {
6000                                 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
6001                                 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
6002                                 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
6003                                 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
6004                                 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
6005                         }
6006                         // additive passes are only darkened by fog, not tinted
6007                         if (r_cg_permutation->fp_FogColor)
6008                         {
6009                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6010                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6011                                 else
6012                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6013                                 CHECKCGERROR
6014                         }
6015                         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
6016                         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
6017                         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
6018                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(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
6019                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(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
6020                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6021                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6022                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6023                 }
6024                 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
6025                 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
6026                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6027                 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
6028                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6029                 if (r_cg_permutation->fp_Color_Pants)
6030                 {
6031                         if (rsurface.texture->pantstexture)
6032                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6033                         else
6034                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6035                         CHECKCGERROR
6036                 }
6037                 if (r_cg_permutation->fp_Color_Shirt)
6038                 {
6039                         if (rsurface.texture->shirttexture)
6040                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6041                         else
6042                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6043                         CHECKCGERROR
6044                 }
6045                 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
6046                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6047                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6048                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6049                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6050                 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
6051                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6052
6053         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6054         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6055         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6056                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6057                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6058                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6059                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6060                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6061                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6062                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6063                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6064                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6065                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6066                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6067                 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
6068                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6069                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6070                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6071                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6072                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6073                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6074                 {
6075                         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
6076                         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
6077                         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
6078                 }
6079                 else
6080                 {
6081                         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
6082                 }
6083                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6084                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6085                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6086                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6087                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6088                 {
6089                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6090                         if (rsurface.rtlight)
6091                         {
6092                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6093                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6094                         }
6095                 }
6096
6097                 CHECKGLERROR
6098 #endif
6099                 break;
6100         case RENDERPATH_GL13:
6101         case RENDERPATH_GL11:
6102                 break;
6103         }
6104 }
6105
6106 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6107 {
6108         // select a permutation of the lighting shader appropriate to this
6109         // combination of texture, entity, light source, and fogging, only use the
6110         // minimum features necessary to avoid wasting rendering time in the
6111         // fragment shader on features that are not being used
6112         unsigned int permutation = 0;
6113         unsigned int mode = 0;
6114         const float *lightcolorbase = rtlight->currentcolor;
6115         float ambientscale = rtlight->ambientscale;
6116         float diffusescale = rtlight->diffusescale;
6117         float specularscale = rtlight->specularscale;
6118         // this is the location of the light in view space
6119         vec3_t viewlightorigin;
6120         // this transforms from view space (camera) to light space (cubemap)
6121         matrix4x4_t viewtolight;
6122         matrix4x4_t lighttoview;
6123         float viewtolight16f[16];
6124         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6125         // light source
6126         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6127         if (rtlight->currentcubemap != r_texture_whitecube)
6128                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6129         if (diffusescale > 0)
6130                 permutation |= SHADERPERMUTATION_DIFFUSE;
6131         if (specularscale > 0)
6132         {
6133                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6134                 if (r_shadow_glossexact.integer)
6135                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6136         }
6137         if (r_shadow_usingshadowmap2d)
6138         {
6139                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6140                 if (r_shadow_shadowmapvsdct)
6141                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6142
6143                 if (r_shadow_shadowmapsampler)
6144                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6145                 if (r_shadow_shadowmappcf > 1)
6146                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6147                 else if (r_shadow_shadowmappcf)
6148                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6149         }
6150         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6151         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6152         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6153         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6154         switch(vid.renderpath)
6155         {
6156         case RENDERPATH_D3D9:
6157 #ifdef SUPPORTD3D
6158                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6159                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6160                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6161                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6162                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6163                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6164                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6165                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6166                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6167                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6168                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6169
6170                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6171                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6172                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6173                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6174                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6175                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6176 #endif
6177                 break;
6178         case RENDERPATH_D3D10:
6179                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6180                 break;
6181         case RENDERPATH_D3D11:
6182                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6183                 break;
6184         case RENDERPATH_GL20:
6185                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6186                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6187                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6188                 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);
6189                 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);
6190                 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);
6191                 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]);
6192                 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]);
6193                 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) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6194                 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]);
6195                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6196
6197                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6198                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6199                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6200                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6201                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6202                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6203                 break;
6204         case RENDERPATH_CGGL:
6205 #ifdef SUPPORTCG
6206                 R_SetupShader_SetPermutationCG(mode, permutation);
6207                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6208                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6209                 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
6210                 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
6211                 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
6212                 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
6213                 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
6214                 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) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6215                 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
6216                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6217
6218                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6219                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6220                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6221                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6222                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6223                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6224 #endif
6225                 break;
6226         case RENDERPATH_GL13:
6227         case RENDERPATH_GL11:
6228                 break;
6229         }
6230 }
6231
6232 #define SKINFRAME_HASH 1024
6233
6234 typedef struct
6235 {
6236         int loadsequence; // incremented each level change
6237         memexpandablearray_t array;
6238         skinframe_t *hash[SKINFRAME_HASH];
6239 }
6240 r_skinframe_t;
6241 r_skinframe_t r_skinframe;
6242
6243 void R_SkinFrame_PrepareForPurge(void)
6244 {
6245         r_skinframe.loadsequence++;
6246         // wrap it without hitting zero
6247         if (r_skinframe.loadsequence >= 200)
6248                 r_skinframe.loadsequence = 1;
6249 }
6250
6251 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6252 {
6253         if (!skinframe)
6254                 return;
6255         // mark the skinframe as used for the purging code
6256         skinframe->loadsequence = r_skinframe.loadsequence;
6257 }
6258
6259 void R_SkinFrame_Purge(void)
6260 {
6261         int i;
6262         skinframe_t *s;
6263         for (i = 0;i < SKINFRAME_HASH;i++)
6264         {
6265                 for (s = r_skinframe.hash[i];s;s = s->next)
6266                 {
6267                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6268                         {
6269                                 if (s->merged == s->base)
6270                                         s->merged = NULL;
6271                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6272                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6273                                 R_PurgeTexture(s->merged);s->merged = NULL;
6274                                 R_PurgeTexture(s->base  );s->base   = NULL;
6275                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6276                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6277                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6278                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6279                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6280                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6281                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6282                                 s->loadsequence = 0;
6283                         }
6284                 }
6285         }
6286 }
6287
6288 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6289         skinframe_t *item;
6290         char basename[MAX_QPATH];
6291
6292         Image_StripImageExtension(name, basename, sizeof(basename));
6293
6294         if( last == NULL ) {
6295                 int hashindex;
6296                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6297                 item = r_skinframe.hash[hashindex];
6298         } else {
6299                 item = last->next;
6300         }
6301
6302         // linearly search through the hash bucket
6303         for( ; item ; item = item->next ) {
6304                 if( !strcmp( item->basename, basename ) ) {
6305                         return item;
6306                 }
6307         }
6308         return NULL;
6309 }
6310
6311 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6312 {
6313         skinframe_t *item;
6314         int hashindex;
6315         char basename[MAX_QPATH];
6316
6317         Image_StripImageExtension(name, basename, sizeof(basename));
6318
6319         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6320         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6321                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6322                         break;
6323
6324         if (!item) {
6325                 rtexture_t *dyntexture;
6326                 // check whether its a dynamic texture
6327                 dyntexture = CL_GetDynTexture( basename );
6328                 if (!add && !dyntexture)
6329                         return NULL;
6330                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6331                 memset(item, 0, sizeof(*item));
6332                 strlcpy(item->basename, basename, sizeof(item->basename));
6333                 item->base = dyntexture; // either NULL or dyntexture handle
6334                 item->textureflags = textureflags;
6335                 item->comparewidth = comparewidth;
6336                 item->compareheight = compareheight;
6337                 item->comparecrc = comparecrc;
6338                 item->next = r_skinframe.hash[hashindex];
6339                 r_skinframe.hash[hashindex] = item;
6340         }
6341         else if( item->base == NULL )
6342         {
6343                 rtexture_t *dyntexture;
6344                 // check whether its a dynamic texture
6345                 // 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]
6346                 dyntexture = CL_GetDynTexture( basename );
6347                 item->base = dyntexture; // either NULL or dyntexture handle
6348         }
6349
6350         R_SkinFrame_MarkUsed(item);
6351         return item;
6352 }
6353
6354 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6355         { \
6356                 unsigned long long avgcolor[5], wsum; \
6357                 int pix, comp, w; \
6358                 avgcolor[0] = 0; \
6359                 avgcolor[1] = 0; \
6360                 avgcolor[2] = 0; \
6361                 avgcolor[3] = 0; \
6362                 avgcolor[4] = 0; \
6363                 wsum = 0; \
6364                 for(pix = 0; pix < cnt; ++pix) \
6365                 { \
6366                         w = 0; \
6367                         for(comp = 0; comp < 3; ++comp) \
6368                                 w += getpixel; \
6369                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6370                         { \
6371                                 ++wsum; \
6372                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6373                                 w = getpixel; \
6374                                 for(comp = 0; comp < 3; ++comp) \
6375                                         avgcolor[comp] += getpixel * w; \
6376                                 avgcolor[3] += w; \
6377                         } \
6378                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6379                         avgcolor[4] += getpixel; \
6380                 } \
6381                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6382                         avgcolor[3] = 1; \
6383                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6384                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6385                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6386                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6387         }
6388
6389 extern cvar_t gl_picmip;
6390 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6391 {
6392         int j;
6393         unsigned char *pixels;
6394         unsigned char *bumppixels;
6395         unsigned char *basepixels = NULL;
6396         int basepixels_width = 0;
6397         int basepixels_height = 0;
6398         skinframe_t *skinframe;
6399         rtexture_t *ddsbase = NULL;
6400         qboolean ddshasalpha = false;
6401         float ddsavgcolor[4];
6402         char basename[MAX_QPATH];
6403         int miplevel = R_PicmipForFlags(textureflags);
6404         int savemiplevel = miplevel;
6405         int mymiplevel;
6406
6407         if (cls.state == ca_dedicated)
6408                 return NULL;
6409
6410         // return an existing skinframe if already loaded
6411         // if loading of the first image fails, don't make a new skinframe as it
6412         // would cause all future lookups of this to be missing
6413         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6414         if (skinframe && skinframe->base)
6415                 return skinframe;
6416
6417         Image_StripImageExtension(name, basename, sizeof(basename));
6418
6419         // check for DDS texture file first
6420         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6421         {
6422                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6423                 if (basepixels == NULL)
6424                         return NULL;
6425         }
6426
6427         // FIXME handle miplevel
6428
6429         if (developer_loading.integer)
6430                 Con_Printf("loading skin \"%s\"\n", name);
6431
6432         // we've got some pixels to store, so really allocate this new texture now
6433         if (!skinframe)
6434                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6435         skinframe->stain = NULL;
6436         skinframe->merged = NULL;
6437         skinframe->base = NULL;
6438         skinframe->pants = NULL;
6439         skinframe->shirt = NULL;
6440         skinframe->nmap = NULL;
6441         skinframe->gloss = NULL;
6442         skinframe->glow = NULL;
6443         skinframe->fog = NULL;
6444         skinframe->reflect = NULL;
6445         skinframe->hasalpha = false;
6446
6447         if (ddsbase)
6448         {
6449                 skinframe->base = ddsbase;
6450                 skinframe->hasalpha = ddshasalpha;
6451                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6452                 if (r_loadfog && skinframe->hasalpha)
6453                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6454                 //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]);
6455         }
6456         else
6457         {
6458                 basepixels_width = image_width;
6459                 basepixels_height = image_height;
6460                 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);
6461                 if (textureflags & TEXF_ALPHA)
6462                 {
6463                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6464                         {
6465                                 if (basepixels[j] < 255)
6466                                 {
6467                                         skinframe->hasalpha = true;
6468                                         break;
6469                                 }
6470                         }
6471                         if (r_loadfog && skinframe->hasalpha)
6472                         {
6473                                 // has transparent pixels
6474                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6475                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6476                                 {
6477                                         pixels[j+0] = 255;
6478                                         pixels[j+1] = 255;
6479                                         pixels[j+2] = 255;
6480                                         pixels[j+3] = basepixels[j+3];
6481                                 }
6482                                 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);
6483                                 Mem_Free(pixels);
6484                         }
6485                 }
6486                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6487                 //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]);
6488                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6489                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6490                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6491                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6492         }
6493
6494         if (r_loaddds)
6495         {
6496                 mymiplevel = savemiplevel;
6497                 if (r_loadnormalmap)
6498                         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);
6499                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6500                 if (r_loadgloss)
6501                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6502                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6503                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6504                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6505         }
6506
6507         // _norm is the name used by tenebrae and has been adopted as standard
6508         if (r_loadnormalmap && skinframe->nmap == NULL)
6509         {
6510                 mymiplevel = savemiplevel;
6511                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6512                 {
6513                         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);
6514                         Mem_Free(pixels);
6515                         pixels = NULL;
6516                 }
6517                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6518                 {
6519                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6520                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6521                         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);
6522                         Mem_Free(pixels);
6523                         Mem_Free(bumppixels);
6524                 }
6525                 else if (r_shadow_bumpscale_basetexture.value > 0)
6526                 {
6527                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6528                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6529                         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);
6530                         Mem_Free(pixels);
6531                 }
6532                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6533                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6534         }
6535
6536         // _luma is supported only for tenebrae compatibility
6537         // _glow is the preferred name
6538         mymiplevel = savemiplevel;
6539         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))))
6540         {
6541                 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);
6542                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6543                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6544                 Mem_Free(pixels);pixels = NULL;
6545         }
6546
6547         mymiplevel = savemiplevel;
6548         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6549         {
6550                 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);
6551                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6552                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6553                 Mem_Free(pixels);
6554                 pixels = NULL;
6555         }
6556
6557         mymiplevel = savemiplevel;
6558         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6559         {
6560                 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);
6561                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6562                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6563                 Mem_Free(pixels);
6564                 pixels = NULL;
6565         }
6566
6567         mymiplevel = savemiplevel;
6568         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6569         {
6570                 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);
6571                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6572                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6573                 Mem_Free(pixels);
6574                 pixels = NULL;
6575         }
6576
6577         mymiplevel = savemiplevel;
6578         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6579         {
6580                 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);
6581                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6582                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6583                 Mem_Free(pixels);
6584                 pixels = NULL;
6585         }
6586
6587         if (basepixels)
6588                 Mem_Free(basepixels);
6589
6590         return skinframe;
6591 }
6592
6593 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6594 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6595 {
6596         int i;
6597         unsigned char *temp1, *temp2;
6598         skinframe_t *skinframe;
6599
6600         if (cls.state == ca_dedicated)
6601                 return NULL;
6602
6603         // if already loaded just return it, otherwise make a new skinframe
6604         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6605         if (skinframe && skinframe->base)
6606                 return skinframe;
6607
6608         skinframe->stain = NULL;
6609         skinframe->merged = NULL;
6610         skinframe->base = NULL;
6611         skinframe->pants = NULL;
6612         skinframe->shirt = NULL;
6613         skinframe->nmap = NULL;
6614         skinframe->gloss = NULL;
6615         skinframe->glow = NULL;
6616         skinframe->fog = NULL;
6617         skinframe->reflect = NULL;
6618         skinframe->hasalpha = false;
6619
6620         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6621         if (!skindata)
6622                 return NULL;
6623
6624         if (developer_loading.integer)
6625                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6626
6627         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6628         {
6629                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6630                 temp2 = temp1 + width * height * 4;
6631                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6632                 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);
6633                 Mem_Free(temp1);
6634         }
6635         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6636         if (textureflags & TEXF_ALPHA)
6637         {
6638                 for (i = 3;i < width * height * 4;i += 4)
6639                 {
6640                         if (skindata[i] < 255)
6641                         {
6642                                 skinframe->hasalpha = true;
6643                                 break;
6644                         }
6645                 }
6646                 if (r_loadfog && skinframe->hasalpha)
6647                 {
6648                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6649                         memcpy(fogpixels, skindata, width * height * 4);
6650                         for (i = 0;i < width * height * 4;i += 4)
6651                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6652                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6653                         Mem_Free(fogpixels);
6654                 }
6655         }
6656
6657         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6658         //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]);
6659
6660         return skinframe;
6661 }
6662
6663 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6664 {
6665         int i;
6666         int featuresmask;
6667         skinframe_t *skinframe;
6668
6669         if (cls.state == ca_dedicated)
6670                 return NULL;
6671
6672         // if already loaded just return it, otherwise make a new skinframe
6673         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6674         if (skinframe && skinframe->base)
6675                 return skinframe;
6676
6677         skinframe->stain = NULL;
6678         skinframe->merged = NULL;
6679         skinframe->base = NULL;
6680         skinframe->pants = NULL;
6681         skinframe->shirt = NULL;
6682         skinframe->nmap = NULL;
6683         skinframe->gloss = NULL;
6684         skinframe->glow = NULL;
6685         skinframe->fog = NULL;
6686         skinframe->reflect = NULL;
6687         skinframe->hasalpha = false;
6688
6689         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6690         if (!skindata)
6691                 return NULL;
6692
6693         if (developer_loading.integer)
6694                 Con_Printf("loading quake skin \"%s\"\n", name);
6695
6696         // 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)
6697         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6698         memcpy(skinframe->qpixels, skindata, width*height);
6699         skinframe->qwidth = width;
6700         skinframe->qheight = height;
6701
6702         featuresmask = 0;
6703         for (i = 0;i < width * height;i++)
6704                 featuresmask |= palette_featureflags[skindata[i]];
6705
6706         skinframe->hasalpha = false;
6707         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6708         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6709         skinframe->qgeneratemerged = true;
6710         skinframe->qgeneratebase = skinframe->qhascolormapping;
6711         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6712
6713         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6714         //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]);
6715
6716         return skinframe;
6717 }
6718
6719 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6720 {
6721         int width;
6722         int height;
6723         unsigned char *skindata;
6724
6725         if (!skinframe->qpixels)
6726                 return;
6727
6728         if (!skinframe->qhascolormapping)
6729                 colormapped = false;
6730
6731         if (colormapped)
6732         {
6733                 if (!skinframe->qgeneratebase)
6734                         return;
6735         }
6736         else
6737         {
6738                 if (!skinframe->qgeneratemerged)
6739                         return;
6740         }
6741
6742         width = skinframe->qwidth;
6743         height = skinframe->qheight;
6744         skindata = skinframe->qpixels;
6745
6746         if (skinframe->qgeneratenmap)
6747         {
6748                 unsigned char *temp1, *temp2;
6749                 skinframe->qgeneratenmap = false;
6750                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6751                 temp2 = temp1 + width * height * 4;
6752                 // use either a custom palette or the quake palette
6753                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6754                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6755                 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);
6756                 Mem_Free(temp1);
6757         }
6758
6759         if (skinframe->qgenerateglow)
6760         {
6761                 skinframe->qgenerateglow = false;
6762                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6763         }
6764
6765         if (colormapped)
6766         {
6767                 skinframe->qgeneratebase = false;
6768                 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);
6769                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6770                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6771         }
6772         else
6773         {
6774                 skinframe->qgeneratemerged = false;
6775                 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);
6776         }
6777
6778         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6779         {
6780                 Mem_Free(skinframe->qpixels);
6781                 skinframe->qpixels = NULL;
6782         }
6783 }
6784
6785 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)
6786 {
6787         int i;
6788         skinframe_t *skinframe;
6789
6790         if (cls.state == ca_dedicated)
6791                 return NULL;
6792
6793         // if already loaded just return it, otherwise make a new skinframe
6794         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6795         if (skinframe && skinframe->base)
6796                 return skinframe;
6797
6798         skinframe->stain = NULL;
6799         skinframe->merged = NULL;
6800         skinframe->base = NULL;
6801         skinframe->pants = NULL;
6802         skinframe->shirt = NULL;
6803         skinframe->nmap = NULL;
6804         skinframe->gloss = NULL;
6805         skinframe->glow = NULL;
6806         skinframe->fog = NULL;
6807         skinframe->reflect = NULL;
6808         skinframe->hasalpha = false;
6809
6810         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6811         if (!skindata)
6812                 return NULL;
6813
6814         if (developer_loading.integer)
6815                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6816
6817         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6818         if (textureflags & TEXF_ALPHA)
6819         {
6820                 for (i = 0;i < width * height;i++)
6821                 {
6822                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6823                         {
6824                                 skinframe->hasalpha = true;
6825                                 break;
6826                         }
6827                 }
6828                 if (r_loadfog && skinframe->hasalpha)
6829                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6830         }
6831
6832         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6833         //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]);
6834
6835         return skinframe;
6836 }
6837
6838 skinframe_t *R_SkinFrame_LoadMissing(void)
6839 {
6840         skinframe_t *skinframe;
6841
6842         if (cls.state == ca_dedicated)
6843                 return NULL;
6844
6845         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6846         skinframe->stain = NULL;
6847         skinframe->merged = NULL;
6848         skinframe->base = NULL;
6849         skinframe->pants = NULL;
6850         skinframe->shirt = NULL;
6851         skinframe->nmap = NULL;
6852         skinframe->gloss = NULL;
6853         skinframe->glow = NULL;
6854         skinframe->fog = NULL;
6855         skinframe->reflect = NULL;
6856         skinframe->hasalpha = false;
6857
6858         skinframe->avgcolor[0] = rand() / RAND_MAX;
6859         skinframe->avgcolor[1] = rand() / RAND_MAX;
6860         skinframe->avgcolor[2] = rand() / RAND_MAX;
6861         skinframe->avgcolor[3] = 1;
6862
6863         return skinframe;
6864 }
6865
6866 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6867 typedef struct suffixinfo_s
6868 {
6869         const char *suffix;
6870         qboolean flipx, flipy, flipdiagonal;
6871 }
6872 suffixinfo_t;
6873 static suffixinfo_t suffix[3][6] =
6874 {
6875         {
6876                 {"px",   false, false, false},
6877                 {"nx",   false, false, false},
6878                 {"py",   false, false, false},
6879                 {"ny",   false, false, false},
6880                 {"pz",   false, false, false},
6881                 {"nz",   false, false, false}
6882         },
6883         {
6884                 {"posx", false, false, false},
6885                 {"negx", false, false, false},
6886                 {"posy", false, false, false},
6887                 {"negy", false, false, false},
6888                 {"posz", false, false, false},
6889                 {"negz", false, false, false}
6890         },
6891         {
6892                 {"rt",    true, false,  true},
6893                 {"lf",   false,  true,  true},
6894                 {"ft",    true,  true, false},
6895                 {"bk",   false, false, false},
6896                 {"up",    true, false,  true},
6897                 {"dn",    true, false,  true}
6898         }
6899 };
6900
6901 static int componentorder[4] = {0, 1, 2, 3};
6902
6903 rtexture_t *R_LoadCubemap(const char *basename)
6904 {
6905         int i, j, cubemapsize;
6906         unsigned char *cubemappixels, *image_buffer;
6907         rtexture_t *cubemaptexture;
6908         char name[256];
6909         // must start 0 so the first loadimagepixels has no requested width/height
6910         cubemapsize = 0;
6911         cubemappixels = NULL;
6912         cubemaptexture = NULL;
6913         // keep trying different suffix groups (posx, px, rt) until one loads
6914         for (j = 0;j < 3 && !cubemappixels;j++)
6915         {
6916                 // load the 6 images in the suffix group
6917                 for (i = 0;i < 6;i++)
6918                 {
6919                         // generate an image name based on the base and and suffix
6920                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6921                         // load it
6922                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6923                         {
6924                                 // an image loaded, make sure width and height are equal
6925                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6926                                 {
6927                                         // if this is the first image to load successfully, allocate the cubemap memory
6928                                         if (!cubemappixels && image_width >= 1)
6929                                         {
6930                                                 cubemapsize = image_width;
6931                                                 // note this clears to black, so unavailable sides are black
6932                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6933                                         }
6934                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6935                                         if (cubemappixels)
6936                                                 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);
6937                                 }
6938                                 else
6939                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6940                                 // free the image
6941                                 Mem_Free(image_buffer);
6942                         }
6943                 }
6944         }
6945         // if a cubemap loaded, upload it
6946         if (cubemappixels)
6947         {
6948                 if (developer_loading.integer)
6949                         Con_Printf("loading cubemap \"%s\"\n", basename);
6950
6951                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6952                 Mem_Free(cubemappixels);
6953         }
6954         else
6955         {
6956                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6957                 if (developer_loading.integer)
6958                 {
6959                         Con_Printf("(tried tried images ");
6960                         for (j = 0;j < 3;j++)
6961                                 for (i = 0;i < 6;i++)
6962                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6963                         Con_Print(" and was unable to find any of them).\n");
6964                 }
6965         }
6966         return cubemaptexture;
6967 }
6968
6969 rtexture_t *R_GetCubemap(const char *basename)
6970 {
6971         int i;
6972         for (i = 0;i < r_texture_numcubemaps;i++)
6973                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6974                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6975         if (i >= MAX_CUBEMAPS)
6976                 return r_texture_whitecube;
6977         r_texture_numcubemaps++;
6978         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6979         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6980         return r_texture_cubemaps[i].texture;
6981 }
6982
6983 void R_FreeCubemaps(void)
6984 {
6985         int i;
6986         for (i = 0;i < r_texture_numcubemaps;i++)
6987         {
6988                 if (developer_loading.integer)
6989                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6990                 if (r_texture_cubemaps[i].texture)
6991                         R_FreeTexture(r_texture_cubemaps[i].texture);
6992         }
6993         r_texture_numcubemaps = 0;
6994 }
6995
6996 void R_Main_FreeViewCache(void)
6997 {
6998         if (r_refdef.viewcache.entityvisible)
6999                 Mem_Free(r_refdef.viewcache.entityvisible);
7000         if (r_refdef.viewcache.world_pvsbits)
7001                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7002         if (r_refdef.viewcache.world_leafvisible)
7003                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7004         if (r_refdef.viewcache.world_surfacevisible)
7005                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7006         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7007 }
7008
7009 void R_Main_ResizeViewCache(void)
7010 {
7011         int numentities = r_refdef.scene.numentities;
7012         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7013         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7014         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7015         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7016         if (r_refdef.viewcache.maxentities < numentities)
7017         {
7018                 r_refdef.viewcache.maxentities = numentities;
7019                 if (r_refdef.viewcache.entityvisible)
7020                         Mem_Free(r_refdef.viewcache.entityvisible);
7021                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7022         }
7023         if (r_refdef.viewcache.world_numclusters != numclusters)
7024         {
7025                 r_refdef.viewcache.world_numclusters = numclusters;
7026                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7027                 if (r_refdef.viewcache.world_pvsbits)
7028                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7029                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7030         }
7031         if (r_refdef.viewcache.world_numleafs != numleafs)
7032         {
7033                 r_refdef.viewcache.world_numleafs = numleafs;
7034                 if (r_refdef.viewcache.world_leafvisible)
7035                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7036                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7037         }
7038         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7039         {
7040                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7041                 if (r_refdef.viewcache.world_surfacevisible)
7042                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7043                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7044         }
7045 }
7046
7047 extern rtexture_t *loadingscreentexture;
7048 void gl_main_start(void)
7049 {
7050         loadingscreentexture = NULL;
7051         r_texture_blanknormalmap = NULL;
7052         r_texture_white = NULL;
7053         r_texture_grey128 = NULL;
7054         r_texture_black = NULL;
7055         r_texture_whitecube = NULL;
7056         r_texture_normalizationcube = NULL;
7057         r_texture_fogattenuation = NULL;
7058         r_texture_fogheighttexture = NULL;
7059         r_texture_gammaramps = NULL;
7060         r_texture_numcubemaps = 0;
7061
7062         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7063         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7064
7065         switch(vid.renderpath)
7066         {
7067         case RENDERPATH_GL20:
7068         case RENDERPATH_CGGL:
7069         case RENDERPATH_D3D9:
7070         case RENDERPATH_D3D10:
7071         case RENDERPATH_D3D11:
7072                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7073                 Cvar_SetValueQuick(&gl_combine, 1);
7074                 Cvar_SetValueQuick(&r_glsl, 1);
7075                 r_loadnormalmap = true;
7076                 r_loadgloss = true;
7077                 r_loadfog = false;
7078                 break;
7079         case RENDERPATH_GL13:
7080                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7081                 Cvar_SetValueQuick(&gl_combine, 1);
7082                 Cvar_SetValueQuick(&r_glsl, 0);
7083                 r_loadnormalmap = false;
7084                 r_loadgloss = false;
7085                 r_loadfog = true;
7086                 break;
7087         case RENDERPATH_GL11:
7088                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7089                 Cvar_SetValueQuick(&gl_combine, 0);
7090                 Cvar_SetValueQuick(&r_glsl, 0);
7091                 r_loadnormalmap = false;
7092                 r_loadgloss = false;
7093                 r_loadfog = true;
7094                 break;
7095         }
7096
7097         R_AnimCache_Free();
7098         R_FrameData_Reset();
7099
7100         r_numqueries = 0;
7101         r_maxqueries = 0;
7102         memset(r_queries, 0, sizeof(r_queries));
7103
7104         r_qwskincache = NULL;
7105         r_qwskincache_size = 0;
7106
7107         // set up r_skinframe loading system for textures
7108         memset(&r_skinframe, 0, sizeof(r_skinframe));
7109         r_skinframe.loadsequence = 1;
7110         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7111
7112         r_main_texturepool = R_AllocTexturePool();
7113         R_BuildBlankTextures();
7114         R_BuildNoTexture();
7115         if (vid.support.arb_texture_cube_map)
7116         {
7117                 R_BuildWhiteCube();
7118                 R_BuildNormalizationCube();
7119         }
7120         r_texture_fogattenuation = NULL;
7121         r_texture_fogheighttexture = NULL;
7122         r_texture_gammaramps = NULL;
7123         //r_texture_fogintensity = NULL;
7124         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7125         memset(&r_waterstate, 0, sizeof(r_waterstate));
7126         r_glsl_permutation = NULL;
7127         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7128         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7129         glslshaderstring = NULL;
7130 #ifdef SUPPORTCG
7131         r_cg_permutation = NULL;
7132         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7133         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7134         cgshaderstring = NULL;
7135 #endif
7136 #ifdef SUPPORTD3D
7137         r_hlsl_permutation = NULL;
7138         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7139         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7140         hlslshaderstring = NULL;
7141 #endif
7142         memset(&r_svbsp, 0, sizeof (r_svbsp));
7143
7144         r_refdef.fogmasktable_density = 0;
7145 }
7146
7147 void gl_main_shutdown(void)
7148 {
7149         R_AnimCache_Free();
7150         R_FrameData_Reset();
7151
7152         R_Main_FreeViewCache();
7153
7154         switch(vid.renderpath)
7155         {
7156         case RENDERPATH_GL11:
7157         case RENDERPATH_GL13:
7158         case RENDERPATH_GL20:
7159         case RENDERPATH_CGGL:
7160                 if (r_maxqueries)
7161                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7162                 break;
7163         case RENDERPATH_D3D9:
7164                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7165                 break;
7166         case RENDERPATH_D3D10:
7167                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7168                 break;
7169         case RENDERPATH_D3D11:
7170                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7171                 break;
7172         }
7173
7174         r_numqueries = 0;
7175         r_maxqueries = 0;
7176         memset(r_queries, 0, sizeof(r_queries));
7177
7178         r_qwskincache = NULL;
7179         r_qwskincache_size = 0;
7180
7181         // clear out the r_skinframe state
7182         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7183         memset(&r_skinframe, 0, sizeof(r_skinframe));
7184
7185         if (r_svbsp.nodes)
7186                 Mem_Free(r_svbsp.nodes);
7187         memset(&r_svbsp, 0, sizeof (r_svbsp));
7188         R_FreeTexturePool(&r_main_texturepool);
7189         loadingscreentexture = NULL;
7190         r_texture_blanknormalmap = NULL;
7191         r_texture_white = NULL;
7192         r_texture_grey128 = NULL;
7193         r_texture_black = NULL;
7194         r_texture_whitecube = NULL;
7195         r_texture_normalizationcube = NULL;
7196         r_texture_fogattenuation = NULL;
7197         r_texture_fogheighttexture = NULL;
7198         r_texture_gammaramps = NULL;
7199         r_texture_numcubemaps = 0;
7200         //r_texture_fogintensity = NULL;
7201         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7202         memset(&r_waterstate, 0, sizeof(r_waterstate));
7203         R_GLSL_Restart_f();
7204 }
7205
7206 extern void CL_ParseEntityLump(char *entitystring);
7207 void gl_main_newmap(void)
7208 {
7209         // FIXME: move this code to client
7210         char *entities, entname[MAX_QPATH];
7211         if (r_qwskincache)
7212                 Mem_Free(r_qwskincache);
7213         r_qwskincache = NULL;
7214         r_qwskincache_size = 0;
7215         if (cl.worldmodel)
7216         {
7217                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7218                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7219                 {
7220                         CL_ParseEntityLump(entities);
7221                         Mem_Free(entities);
7222                         return;
7223                 }
7224                 if (cl.worldmodel->brush.entities)
7225                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7226         }
7227         R_Main_FreeViewCache();
7228
7229         R_FrameData_Reset();
7230 }
7231
7232 void GL_Main_Init(void)
7233 {
7234         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7235
7236         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7237         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7238         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7239         if (gamemode == GAME_NEHAHRA)
7240         {
7241                 Cvar_RegisterVariable (&gl_fogenable);
7242                 Cvar_RegisterVariable (&gl_fogdensity);
7243                 Cvar_RegisterVariable (&gl_fogred);
7244                 Cvar_RegisterVariable (&gl_foggreen);
7245                 Cvar_RegisterVariable (&gl_fogblue);
7246                 Cvar_RegisterVariable (&gl_fogstart);
7247                 Cvar_RegisterVariable (&gl_fogend);
7248                 Cvar_RegisterVariable (&gl_skyclip);
7249         }
7250         Cvar_RegisterVariable(&r_motionblur);
7251         Cvar_RegisterVariable(&r_motionblur_maxblur);
7252         Cvar_RegisterVariable(&r_motionblur_bmin);
7253         Cvar_RegisterVariable(&r_motionblur_vmin);
7254         Cvar_RegisterVariable(&r_motionblur_vmax);
7255         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7256         Cvar_RegisterVariable(&r_motionblur_randomize);
7257         Cvar_RegisterVariable(&r_damageblur);
7258         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7259         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7260         Cvar_RegisterVariable(&r_equalize_entities_by);
7261         Cvar_RegisterVariable(&r_equalize_entities_to);
7262         Cvar_RegisterVariable(&r_depthfirst);
7263         Cvar_RegisterVariable(&r_useinfinitefarclip);
7264         Cvar_RegisterVariable(&r_farclip_base);
7265         Cvar_RegisterVariable(&r_farclip_world);
7266         Cvar_RegisterVariable(&r_nearclip);
7267         Cvar_RegisterVariable(&r_showbboxes);
7268         Cvar_RegisterVariable(&r_showsurfaces);
7269         Cvar_RegisterVariable(&r_showtris);
7270         Cvar_RegisterVariable(&r_shownormals);
7271         Cvar_RegisterVariable(&r_showlighting);
7272         Cvar_RegisterVariable(&r_showshadowvolumes);
7273         Cvar_RegisterVariable(&r_showcollisionbrushes);
7274         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7275         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7276         Cvar_RegisterVariable(&r_showdisabledepthtest);
7277         Cvar_RegisterVariable(&r_drawportals);
7278         Cvar_RegisterVariable(&r_drawentities);
7279         Cvar_RegisterVariable(&r_draw2d);
7280         Cvar_RegisterVariable(&r_drawworld);
7281         Cvar_RegisterVariable(&r_cullentities_trace);
7282         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7283         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7284         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7285         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7286         Cvar_RegisterVariable(&r_drawviewmodel);
7287         Cvar_RegisterVariable(&r_drawexteriormodel);
7288         Cvar_RegisterVariable(&r_speeds);
7289         Cvar_RegisterVariable(&r_fullbrights);
7290         Cvar_RegisterVariable(&r_wateralpha);
7291         Cvar_RegisterVariable(&r_dynamic);
7292         Cvar_RegisterVariable(&r_fakelight);
7293         Cvar_RegisterVariable(&r_fakelight_intensity);
7294         Cvar_RegisterVariable(&r_fullbright);
7295         Cvar_RegisterVariable(&r_shadows);
7296         Cvar_RegisterVariable(&r_shadows_darken);
7297         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7298         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7299         Cvar_RegisterVariable(&r_shadows_throwdistance);
7300         Cvar_RegisterVariable(&r_shadows_throwdirection);
7301         Cvar_RegisterVariable(&r_shadows_focus);
7302         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7303         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7304         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7305         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7306         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7307         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7308         Cvar_RegisterVariable(&r_fog_exp2);
7309         Cvar_RegisterVariable(&r_drawfog);
7310         Cvar_RegisterVariable(&r_transparentdepthmasking);
7311         Cvar_RegisterVariable(&r_texture_dds_load);
7312         Cvar_RegisterVariable(&r_texture_dds_save);
7313         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7314         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7315         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7316         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7317         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7318         Cvar_RegisterVariable(&r_textureunits);
7319         Cvar_RegisterVariable(&gl_combine);
7320         Cvar_RegisterVariable(&r_glsl);
7321         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7322         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7323         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7324         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7325         Cvar_RegisterVariable(&r_glsl_postprocess);
7326         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7327         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7328         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7329         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7330         Cvar_RegisterVariable(&r_water);
7331         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7332         Cvar_RegisterVariable(&r_water_clippingplanebias);
7333         Cvar_RegisterVariable(&r_water_refractdistort);
7334         Cvar_RegisterVariable(&r_water_reflectdistort);
7335         Cvar_RegisterVariable(&r_water_scissormode);
7336         Cvar_RegisterVariable(&r_lerpsprites);
7337         Cvar_RegisterVariable(&r_lerpmodels);
7338         Cvar_RegisterVariable(&r_lerplightstyles);
7339         Cvar_RegisterVariable(&r_waterscroll);
7340         Cvar_RegisterVariable(&r_bloom);
7341         Cvar_RegisterVariable(&r_bloom_colorscale);
7342         Cvar_RegisterVariable(&r_bloom_brighten);
7343         Cvar_RegisterVariable(&r_bloom_blur);
7344         Cvar_RegisterVariable(&r_bloom_resolution);
7345         Cvar_RegisterVariable(&r_bloom_colorexponent);
7346         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7347         Cvar_RegisterVariable(&r_hdr);
7348         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7349         Cvar_RegisterVariable(&r_hdr_glowintensity);
7350         Cvar_RegisterVariable(&r_hdr_range);
7351         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7352         Cvar_RegisterVariable(&developer_texturelogging);
7353         Cvar_RegisterVariable(&gl_lightmaps);
7354         Cvar_RegisterVariable(&r_test);
7355         Cvar_RegisterVariable(&r_glsl_saturation);
7356         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7357         Cvar_RegisterVariable(&r_framedatasize);
7358         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7359                 Cvar_SetValue("r_fullbrights", 0);
7360         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7361
7362         Cvar_RegisterVariable(&r_track_sprites);
7363         Cvar_RegisterVariable(&r_track_sprites_flags);
7364         Cvar_RegisterVariable(&r_track_sprites_scalew);
7365         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7366         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7367         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7368 }
7369
7370 extern void R_Textures_Init(void);
7371 extern void GL_Draw_Init(void);
7372 extern void GL_Main_Init(void);
7373 extern void R_Shadow_Init(void);
7374 extern void R_Sky_Init(void);
7375 extern void GL_Surf_Init(void);
7376 extern void R_Particles_Init(void);
7377 extern void R_Explosion_Init(void);
7378 extern void gl_backend_init(void);
7379 extern void Sbar_Init(void);
7380 extern void R_LightningBeams_Init(void);
7381 extern void Mod_RenderInit(void);
7382 extern void Font_Init(void);
7383
7384 void Render_Init(void)
7385 {
7386         gl_backend_init();
7387         R_Textures_Init();
7388         GL_Main_Init();
7389         Font_Init();
7390         GL_Draw_Init();
7391         R_Shadow_Init();
7392         R_Sky_Init();
7393         GL_Surf_Init();
7394         Sbar_Init();
7395         R_Particles_Init();
7396         R_Explosion_Init();
7397         R_LightningBeams_Init();
7398         Mod_RenderInit();
7399 }
7400
7401 /*
7402 ===============
7403 GL_Init
7404 ===============
7405 */
7406 extern char *ENGINE_EXTENSIONS;
7407 void GL_Init (void)
7408 {
7409         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7410         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7411         gl_version = (const char *)qglGetString(GL_VERSION);
7412         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7413
7414         if (!gl_extensions)
7415                 gl_extensions = "";
7416         if (!gl_platformextensions)
7417                 gl_platformextensions = "";
7418
7419         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7420         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7421         Con_Printf("GL_VERSION: %s\n", gl_version);
7422         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7423         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7424
7425         VID_CheckExtensions();
7426
7427         // LordHavoc: report supported extensions
7428         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7429
7430         // clear to black (loading plaque will be seen over this)
7431         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7432 }
7433
7434 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7435 {
7436         int i;
7437         mplane_t *p;
7438         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7439         {
7440                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7441                 if (i == 4)
7442                         continue;
7443                 p = r_refdef.view.frustum + i;
7444                 switch(p->signbits)
7445                 {
7446                 default:
7447                 case 0:
7448                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7449                                 return true;
7450                         break;
7451                 case 1:
7452                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7453                                 return true;
7454                         break;
7455                 case 2:
7456                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7457                                 return true;
7458                         break;
7459                 case 3:
7460                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7461                                 return true;
7462                         break;
7463                 case 4:
7464                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7465                                 return true;
7466                         break;
7467                 case 5:
7468                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7469                                 return true;
7470                         break;
7471                 case 6:
7472                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7473                                 return true;
7474                         break;
7475                 case 7:
7476                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7477                                 return true;
7478                         break;
7479                 }
7480         }
7481         return false;
7482 }
7483
7484 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7485 {
7486         int i;
7487         const mplane_t *p;
7488         for (i = 0;i < numplanes;i++)
7489         {
7490                 p = planes + i;
7491                 switch(p->signbits)
7492                 {
7493                 default:
7494                 case 0:
7495                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7496                                 return true;
7497                         break;
7498                 case 1:
7499                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7500                                 return true;
7501                         break;
7502                 case 2:
7503                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7504                                 return true;
7505                         break;
7506                 case 3:
7507                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7508                                 return true;
7509                         break;
7510                 case 4:
7511                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7512                                 return true;
7513                         break;
7514                 case 5:
7515                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7516                                 return true;
7517                         break;
7518                 case 6:
7519                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7520                                 return true;
7521                         break;
7522                 case 7:
7523                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7524                                 return true;
7525                         break;
7526                 }
7527         }
7528         return false;
7529 }
7530
7531 //==================================================================================
7532
7533 // LordHavoc: this stores temporary data used within the same frame
7534
7535 qboolean r_framedata_failed;
7536 static size_t r_framedata_size;
7537 static size_t r_framedata_current;
7538 static void *r_framedata_base;
7539
7540 void R_FrameData_Reset(void)
7541 {
7542         if (r_framedata_base)
7543                 Mem_Free(r_framedata_base);
7544         r_framedata_base = NULL;
7545         r_framedata_size = 0;
7546         r_framedata_current = 0;
7547         r_framedata_failed = false;
7548 }
7549
7550 void R_FrameData_NewFrame(void)
7551 {
7552         size_t wantedsize;
7553         if (r_framedata_failed)
7554                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7555         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7556         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7557         if (r_framedata_size != wantedsize)
7558         {
7559                 r_framedata_size = wantedsize;
7560                 if (r_framedata_base)
7561                         Mem_Free(r_framedata_base);
7562                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7563         }
7564         r_framedata_current = 0;
7565         r_framedata_failed = false;
7566 }
7567
7568 void *R_FrameData_Alloc(size_t size)
7569 {
7570         void *data;
7571
7572         // align to 16 byte boundary
7573         size = (size + 15) & ~15;
7574         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7575         r_framedata_current += size;
7576
7577         // check overflow
7578         if (r_framedata_current > r_framedata_size)
7579                 r_framedata_failed = true;
7580
7581         // return NULL on everything after a failure
7582         if (r_framedata_failed)
7583                 return NULL;
7584
7585         return data;
7586 }
7587
7588 void *R_FrameData_Store(size_t size, void *data)
7589 {
7590         void *d = R_FrameData_Alloc(size);
7591         if (d)
7592                 memcpy(d, data, size);
7593         return d;
7594 }
7595
7596 //==================================================================================
7597
7598 // LordHavoc: animcache originally written by Echon, rewritten since then
7599
7600 /**
7601  * Animation cache prevents re-generating mesh data for an animated model
7602  * multiple times in one frame for lighting, shadowing, reflections, etc.
7603  */
7604
7605 void R_AnimCache_Free(void)
7606 {
7607 }
7608
7609 void R_AnimCache_ClearCache(void)
7610 {
7611         int i;
7612         entity_render_t *ent;
7613
7614         for (i = 0;i < r_refdef.scene.numentities;i++)
7615         {
7616                 ent = r_refdef.scene.entities[i];
7617                 ent->animcache_vertex3f = NULL;
7618                 ent->animcache_normal3f = NULL;
7619                 ent->animcache_svector3f = NULL;
7620                 ent->animcache_tvector3f = NULL;
7621                 ent->animcache_vertexposition = NULL;
7622                 ent->animcache_vertexmesh = NULL;
7623                 ent->animcache_vertexpositionbuffer = NULL;
7624                 ent->animcache_vertexmeshbuffer = NULL;
7625         }
7626 }
7627
7628 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7629 {
7630         int i;
7631
7632         // identical memory layout, so no need to allocate...
7633         // this also provides the vertexposition structure to everything, e.g.
7634         // depth masked rendering currently uses it even if having separate
7635         // arrays
7636         // NOTE: get rid of this optimization if changing it to e.g. 4f
7637         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7638
7639         // TODO:
7640         // get rid of following uses of VERTEXPOSITION, change to the array:
7641         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7642         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7643         // R_DrawTextureSurfaceList_DepthOnly
7644         // R_Q1BSP_DrawShadowMap
7645
7646         switch(vid.renderpath)
7647         {
7648         case RENDERPATH_GL20:
7649         case RENDERPATH_CGGL:
7650                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7651                 if (gl_mesh_separatearrays.integer)
7652                         return;
7653                 break;
7654         case RENDERPATH_D3D9:
7655         case RENDERPATH_D3D10:
7656         case RENDERPATH_D3D11:
7657                 // always need the meshbuffers
7658                 break;
7659         case RENDERPATH_GL13:
7660         case RENDERPATH_GL11:
7661                 // never need the meshbuffers
7662                 return;
7663         }
7664
7665         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7666                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7667         /*
7668         if (!ent->animcache_vertexposition)
7669                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7670         */
7671         if (ent->animcache_vertexposition)
7672         {
7673                 /*
7674                 for (i = 0;i < numvertices;i++)
7675                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7676                 */
7677                 // TODO: upload vertex buffer?
7678         }
7679         if (ent->animcache_vertexmesh)
7680         {
7681                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7682                 for (i = 0;i < numvertices;i++)
7683                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7684                 if (ent->animcache_svector3f)
7685                         for (i = 0;i < numvertices;i++)
7686                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7687                 if (ent->animcache_tvector3f)
7688                         for (i = 0;i < numvertices;i++)
7689                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7690                 if (ent->animcache_normal3f)
7691                         for (i = 0;i < numvertices;i++)
7692                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7693                 // TODO: upload vertex buffer?
7694         }
7695 }
7696
7697 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7698 {
7699         dp_model_t *model = ent->model;
7700         int numvertices;
7701         // see if it's already cached this frame
7702         if (ent->animcache_vertex3f)
7703         {
7704                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7705                 if (wantnormals || wanttangents)
7706                 {
7707                         if (ent->animcache_normal3f)
7708                                 wantnormals = false;
7709                         if (ent->animcache_svector3f)
7710                                 wanttangents = false;
7711                         if (wantnormals || wanttangents)
7712                         {
7713                                 numvertices = model->surfmesh.num_vertices;
7714                                 if (wantnormals)
7715                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7716                                 if (wanttangents)
7717                                 {
7718                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7719                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7720                                 }
7721                                 if (!r_framedata_failed)
7722                                 {
7723                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7724                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7725                                 }
7726                         }
7727                 }
7728         }
7729         else
7730         {
7731                 // see if this ent is worth caching
7732                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7733                         return false;
7734                 // get some memory for this entity and generate mesh data
7735                 numvertices = model->surfmesh.num_vertices;
7736                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7737                 if (wantnormals)
7738                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7739                 if (wanttangents)
7740                 {
7741                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7742                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7743                 }
7744                 if (!r_framedata_failed)
7745                 {
7746                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7747                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7748                 }
7749         }
7750         return !r_framedata_failed;
7751 }
7752
7753 void R_AnimCache_CacheVisibleEntities(void)
7754 {
7755         int i;
7756         qboolean wantnormals = true;
7757         qboolean wanttangents = !r_showsurfaces.integer;
7758
7759         switch(vid.renderpath)
7760         {
7761         case RENDERPATH_GL20:
7762         case RENDERPATH_CGGL:
7763         case RENDERPATH_D3D9:
7764         case RENDERPATH_D3D10:
7765         case RENDERPATH_D3D11:
7766                 break;
7767         case RENDERPATH_GL13:
7768         case RENDERPATH_GL11:
7769                 wanttangents = false;
7770                 break;
7771         }
7772
7773         if (r_shownormals.integer)
7774                 wanttangents = wantnormals = true;
7775
7776         // TODO: thread this
7777         // NOTE: R_PrepareRTLights() also caches entities
7778
7779         for (i = 0;i < r_refdef.scene.numentities;i++)
7780                 if (r_refdef.viewcache.entityvisible[i])
7781                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7782 }
7783
7784 //==================================================================================
7785
7786 static void R_View_UpdateEntityLighting (void)
7787 {
7788         int i;
7789         entity_render_t *ent;
7790         vec3_t tempdiffusenormal, avg;
7791         vec_t f, fa, fd, fdd;
7792         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7793
7794         for (i = 0;i < r_refdef.scene.numentities;i++)
7795         {
7796                 ent = r_refdef.scene.entities[i];
7797
7798                 // skip unseen models
7799                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7800                         continue;
7801
7802                 // skip bsp models
7803                 if (ent->model && ent->model->brush.num_leafs)
7804                 {
7805                         // TODO: use modellight for r_ambient settings on world?
7806                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7807                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7808                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7809                         continue;
7810                 }
7811
7812                 // fetch the lighting from the worldmodel data
7813                 VectorClear(ent->modellight_ambient);
7814                 VectorClear(ent->modellight_diffuse);
7815                 VectorClear(tempdiffusenormal);
7816                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7817                 {
7818                         vec3_t org;
7819                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7820                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7821                         if(ent->flags & RENDER_EQUALIZE)
7822                         {
7823                                 // first fix up ambient lighting...
7824                                 if(r_equalize_entities_minambient.value > 0)
7825                                 {
7826                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7827                                         if(fd > 0)
7828                                         {
7829                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7830                                                 if(fa < r_equalize_entities_minambient.value * fd)
7831                                                 {
7832                                                         // solve:
7833                                                         //   fa'/fd' = minambient
7834                                                         //   fa'+0.25*fd' = fa+0.25*fd
7835                                                         //   ...
7836                                                         //   fa' = fd' * minambient
7837                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7838                                                         //   ...
7839                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7840                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7841                                                         //   ...
7842                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7843                                                         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
7844                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7845                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7846                                                 }
7847                                         }
7848                                 }
7849
7850                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7851                                 {
7852                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7853                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7854                                         if(f > 0)
7855                                         {
7856                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7857                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7858                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7859                                         }
7860                                 }
7861                         }
7862                 }
7863                 else // highly rare
7864                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7865
7866                 // move the light direction into modelspace coordinates for lighting code
7867                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7868                 if(VectorLength2(ent->modellight_lightdir) == 0)
7869                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7870                 VectorNormalize(ent->modellight_lightdir);
7871         }
7872 }
7873
7874 #define MAX_LINEOFSIGHTTRACES 64
7875
7876 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7877 {
7878         int i;
7879         vec3_t boxmins, boxmaxs;
7880         vec3_t start;
7881         vec3_t end;
7882         dp_model_t *model = r_refdef.scene.worldmodel;
7883
7884         if (!model || !model->brush.TraceLineOfSight)
7885                 return true;
7886
7887         // expand the box a little
7888         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7889         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7890         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7891         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7892         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7893         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7894
7895         // return true if eye is inside enlarged box
7896         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7897                 return true;
7898
7899         // try center
7900         VectorCopy(eye, start);
7901         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7902         if (model->brush.TraceLineOfSight(model, start, end))
7903                 return true;
7904
7905         // try various random positions
7906         for (i = 0;i < numsamples;i++)
7907         {
7908                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7909                 if (model->brush.TraceLineOfSight(model, start, end))
7910                         return true;
7911         }
7912
7913         return false;
7914 }
7915
7916
7917 static void R_View_UpdateEntityVisible (void)
7918 {
7919         int i;
7920         int renderimask;
7921         int samples;
7922         entity_render_t *ent;
7923
7924         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7925                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7926                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7927                 :                                                          RENDER_EXTERIORMODEL;
7928         if (!r_drawviewmodel.integer)
7929                 renderimask |= RENDER_VIEWMODEL;
7930         if (!r_drawexteriormodel.integer)
7931                 renderimask |= RENDER_EXTERIORMODEL;
7932         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7933         {
7934                 // worldmodel can check visibility
7935                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7936                 for (i = 0;i < r_refdef.scene.numentities;i++)
7937                 {
7938                         ent = r_refdef.scene.entities[i];
7939                         if (!(ent->flags & renderimask))
7940                         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)))
7941                         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))
7942                                 r_refdef.viewcache.entityvisible[i] = true;
7943                 }
7944                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7945                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7946                 {
7947                         for (i = 0;i < r_refdef.scene.numentities;i++)
7948                         {
7949                                 ent = r_refdef.scene.entities[i];
7950                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7951                                 {
7952                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7953                                         if (samples < 0)
7954                                                 continue; // temp entities do pvs only
7955                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7956                                                 ent->last_trace_visibility = realtime;
7957                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7958                                                 r_refdef.viewcache.entityvisible[i] = 0;
7959                                 }
7960                         }
7961                 }
7962         }
7963         else
7964         {
7965                 // no worldmodel or it can't check visibility
7966                 for (i = 0;i < r_refdef.scene.numentities;i++)
7967                 {
7968                         ent = r_refdef.scene.entities[i];
7969                         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));
7970                 }
7971         }
7972 }
7973
7974 /// only used if skyrendermasked, and normally returns false
7975 int R_DrawBrushModelsSky (void)
7976 {
7977         int i, sky;
7978         entity_render_t *ent;
7979
7980         sky = false;
7981         for (i = 0;i < r_refdef.scene.numentities;i++)
7982         {
7983                 if (!r_refdef.viewcache.entityvisible[i])
7984                         continue;
7985                 ent = r_refdef.scene.entities[i];
7986                 if (!ent->model || !ent->model->DrawSky)
7987                         continue;
7988                 ent->model->DrawSky(ent);
7989                 sky = true;
7990         }
7991         return sky;
7992 }
7993
7994 static void R_DrawNoModel(entity_render_t *ent);
7995 static void R_DrawModels(void)
7996 {
7997         int i;
7998         entity_render_t *ent;
7999
8000         for (i = 0;i < r_refdef.scene.numentities;i++)
8001         {
8002                 if (!r_refdef.viewcache.entityvisible[i])
8003                         continue;
8004                 ent = r_refdef.scene.entities[i];
8005                 r_refdef.stats.entities++;
8006                 if (ent->model && ent->model->Draw != NULL)
8007                         ent->model->Draw(ent);
8008                 else
8009                         R_DrawNoModel(ent);
8010         }
8011 }
8012
8013 static void R_DrawModelsDepth(void)
8014 {
8015         int i;
8016         entity_render_t *ent;
8017
8018         for (i = 0;i < r_refdef.scene.numentities;i++)
8019         {
8020                 if (!r_refdef.viewcache.entityvisible[i])
8021                         continue;
8022                 ent = r_refdef.scene.entities[i];
8023                 if (ent->model && ent->model->DrawDepth != NULL)
8024                         ent->model->DrawDepth(ent);
8025         }
8026 }
8027
8028 static void R_DrawModelsDebug(void)
8029 {
8030         int i;
8031         entity_render_t *ent;
8032
8033         for (i = 0;i < r_refdef.scene.numentities;i++)
8034         {
8035                 if (!r_refdef.viewcache.entityvisible[i])
8036                         continue;
8037                 ent = r_refdef.scene.entities[i];
8038                 if (ent->model && ent->model->DrawDebug != NULL)
8039                         ent->model->DrawDebug(ent);
8040         }
8041 }
8042
8043 static void R_DrawModelsAddWaterPlanes(void)
8044 {
8045         int i;
8046         entity_render_t *ent;
8047
8048         for (i = 0;i < r_refdef.scene.numentities;i++)
8049         {
8050                 if (!r_refdef.viewcache.entityvisible[i])
8051                         continue;
8052                 ent = r_refdef.scene.entities[i];
8053                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8054                         ent->model->DrawAddWaterPlanes(ent);
8055         }
8056 }
8057
8058 static void R_View_SetFrustum(const int *scissor)
8059 {
8060         int i;
8061         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8062         vec3_t forward, left, up, origin, v;
8063
8064         if(scissor)
8065         {
8066                 // flipped x coordinates (because x points left here)
8067                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8068                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8069
8070                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8071                 switch(vid.renderpath)
8072                 {
8073                         case RENDERPATH_D3D9:
8074                         case RENDERPATH_D3D10:
8075                         case RENDERPATH_D3D11:
8076                                 // non-flipped y coordinates
8077                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8078                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8079                                 break;
8080                         case RENDERPATH_GL11:
8081                         case RENDERPATH_GL13:
8082                         case RENDERPATH_GL20:
8083                         case RENDERPATH_CGGL:
8084                                 // non-flipped y coordinates
8085                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8086                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8087                                 break;
8088                 }
8089         }
8090
8091         // we can't trust r_refdef.view.forward and friends in reflected scenes
8092         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8093
8094 #if 0
8095         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8096         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8097         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8098         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8099         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8100         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8101         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8102         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8103         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8104         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8105         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8106         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8107 #endif
8108
8109 #if 0
8110         zNear = r_refdef.nearclip;
8111         nudge = 1.0 - 1.0 / (1<<23);
8112         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8113         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8114         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8115         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8116         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8117         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8118         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8119         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8120 #endif
8121
8122
8123
8124 #if 0
8125         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8126         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8127         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8128         r_refdef.view.frustum[0].dist = m[15] - m[12];
8129
8130         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8131         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8132         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8133         r_refdef.view.frustum[1].dist = m[15] + m[12];
8134
8135         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8136         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8137         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8138         r_refdef.view.frustum[2].dist = m[15] - m[13];
8139
8140         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8141         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8142         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8143         r_refdef.view.frustum[3].dist = m[15] + m[13];
8144
8145         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8146         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8147         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8148         r_refdef.view.frustum[4].dist = m[15] - m[14];
8149
8150         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8151         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8152         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8153         r_refdef.view.frustum[5].dist = m[15] + m[14];
8154 #endif
8155
8156         if (r_refdef.view.useperspective)
8157         {
8158                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8159                 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]);
8160                 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]);
8161                 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]);
8162                 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]);
8163
8164                 // then the normals from the corners relative to origin
8165                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8166                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8167                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8168                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8169
8170                 // in a NORMAL view, forward cross left == up
8171                 // in a REFLECTED view, forward cross left == down
8172                 // so our cross products above need to be adjusted for a left handed coordinate system
8173                 CrossProduct(forward, left, v);
8174                 if(DotProduct(v, up) < 0)
8175                 {
8176                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8177                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8178                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8179                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8180                 }
8181
8182                 // Leaving those out was a mistake, those were in the old code, and they
8183                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8184                 // I couldn't reproduce it after adding those normalizations. --blub
8185                 VectorNormalize(r_refdef.view.frustum[0].normal);
8186                 VectorNormalize(r_refdef.view.frustum[1].normal);
8187                 VectorNormalize(r_refdef.view.frustum[2].normal);
8188                 VectorNormalize(r_refdef.view.frustum[3].normal);
8189
8190                 // make the corners absolute
8191                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8192                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8193                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8194                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8195
8196                 // one more normal
8197                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8198
8199                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8200                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8201                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8202                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8203                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8204         }
8205         else
8206         {
8207                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8208                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8209                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8210                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8211                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8212                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8213                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8214                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8215                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8216                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8217         }
8218         r_refdef.view.numfrustumplanes = 5;
8219
8220         if (r_refdef.view.useclipplane)
8221         {
8222                 r_refdef.view.numfrustumplanes = 6;
8223                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8224         }
8225
8226         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8227                 PlaneClassify(r_refdef.view.frustum + i);
8228
8229         // LordHavoc: note to all quake engine coders, Quake had a special case
8230         // for 90 degrees which assumed a square view (wrong), so I removed it,
8231         // Quake2 has it disabled as well.
8232
8233         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8234         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8235         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8236         //PlaneClassify(&frustum[0]);
8237
8238         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8239         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8240         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8241         //PlaneClassify(&frustum[1]);
8242
8243         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8244         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8245         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8246         //PlaneClassify(&frustum[2]);
8247
8248         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8249         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8250         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8251         //PlaneClassify(&frustum[3]);
8252
8253         // nearclip plane
8254         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8255         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8256         //PlaneClassify(&frustum[4]);
8257 }
8258
8259 void R_View_UpdateWithScissor(const int *myscissor)
8260 {
8261         R_Main_ResizeViewCache();
8262         R_View_SetFrustum(myscissor);
8263         R_View_WorldVisibility(r_refdef.view.useclipplane);
8264         R_View_UpdateEntityVisible();
8265         R_View_UpdateEntityLighting();
8266 }
8267
8268 void R_View_Update(void)
8269 {
8270         R_Main_ResizeViewCache();
8271         R_View_SetFrustum(NULL);
8272         R_View_WorldVisibility(r_refdef.view.useclipplane);
8273         R_View_UpdateEntityVisible();
8274         R_View_UpdateEntityLighting();
8275 }
8276
8277 void R_SetupView(qboolean allowwaterclippingplane)
8278 {
8279         const float *customclipplane = NULL;
8280         float plane[4];
8281         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8282         {
8283                 // LordHavoc: couldn't figure out how to make this approach the
8284                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8285                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8286                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8287                         dist = r_refdef.view.clipplane.dist;
8288                 plane[0] = r_refdef.view.clipplane.normal[0];
8289                 plane[1] = r_refdef.view.clipplane.normal[1];
8290                 plane[2] = r_refdef.view.clipplane.normal[2];
8291                 plane[3] = dist;
8292                 customclipplane = plane;
8293         }
8294
8295         if (!r_refdef.view.useperspective)
8296                 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);
8297         else if (vid.stencil && r_useinfinitefarclip.integer)
8298                 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);
8299         else
8300                 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);
8301         R_SetViewport(&r_refdef.view.viewport);
8302 }
8303
8304 void R_EntityMatrix(const matrix4x4_t *matrix)
8305 {
8306         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8307         {
8308                 gl_modelmatrixchanged = false;
8309                 gl_modelmatrix = *matrix;
8310                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8311                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8312                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8313                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8314                 CHECKGLERROR
8315                 switch(vid.renderpath)
8316                 {
8317                 case RENDERPATH_D3D9:
8318 #ifdef SUPPORTD3D
8319                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8320                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8321 #endif
8322                         break;
8323                 case RENDERPATH_D3D10:
8324                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8325                         break;
8326                 case RENDERPATH_D3D11:
8327                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8328                         break;
8329                 case RENDERPATH_GL20:
8330                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8331                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8332                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8333                         break;
8334                 case RENDERPATH_CGGL:
8335 #ifdef SUPPORTCG
8336                         CHECKCGERROR
8337                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8338                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8339                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8340 #endif
8341                         break;
8342                 case RENDERPATH_GL13:
8343                 case RENDERPATH_GL11:
8344                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8345                         break;
8346                 }
8347         }
8348 }
8349
8350 void R_ResetViewRendering2D(void)
8351 {
8352         r_viewport_t viewport;
8353         DrawQ_Finish();
8354
8355         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8356         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);
8357         R_SetViewport(&viewport);
8358         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8359         GL_Color(1, 1, 1, 1);
8360         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8361         GL_BlendFunc(GL_ONE, GL_ZERO);
8362         GL_AlphaTest(false);
8363         GL_ScissorTest(false);
8364         GL_DepthMask(false);
8365         GL_DepthRange(0, 1);
8366         GL_DepthTest(false);
8367         GL_DepthFunc(GL_LEQUAL);
8368         R_EntityMatrix(&identitymatrix);
8369         R_Mesh_ResetTextureState();
8370         GL_PolygonOffset(0, 0);
8371         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8372         switch(vid.renderpath)
8373         {
8374         case RENDERPATH_GL11:
8375         case RENDERPATH_GL13:
8376         case RENDERPATH_GL20:
8377         case RENDERPATH_CGGL:
8378                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8379                 break;
8380         case RENDERPATH_D3D9:
8381         case RENDERPATH_D3D10:
8382         case RENDERPATH_D3D11:
8383                 break;
8384         }
8385         GL_CullFace(GL_NONE);
8386 }
8387
8388 void R_ResetViewRendering3D(void)
8389 {
8390         DrawQ_Finish();
8391
8392         R_SetupView(true);
8393         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8394         GL_Color(1, 1, 1, 1);
8395         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8396         GL_BlendFunc(GL_ONE, GL_ZERO);
8397         GL_AlphaTest(false);
8398         GL_ScissorTest(true);
8399         GL_DepthMask(true);
8400         GL_DepthRange(0, 1);
8401         GL_DepthTest(true);
8402         GL_DepthFunc(GL_LEQUAL);
8403         R_EntityMatrix(&identitymatrix);
8404         R_Mesh_ResetTextureState();
8405         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8406         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8407         switch(vid.renderpath)
8408         {
8409         case RENDERPATH_GL11:
8410         case RENDERPATH_GL13:
8411         case RENDERPATH_GL20:
8412         case RENDERPATH_CGGL:
8413                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8414                 break;
8415         case RENDERPATH_D3D9:
8416         case RENDERPATH_D3D10:
8417         case RENDERPATH_D3D11:
8418                 break;
8419         }
8420         GL_CullFace(r_refdef.view.cullface_back);
8421 }
8422
8423 /*
8424 ================
8425 R_RenderView_UpdateViewVectors
8426 ================
8427 */
8428 static void R_RenderView_UpdateViewVectors(void)
8429 {
8430         // break apart the view matrix into vectors for various purposes
8431         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8432         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8433         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8434         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8435         // make an inverted copy of the view matrix for tracking sprites
8436         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8437 }
8438
8439 void R_RenderScene(void);
8440 void R_RenderWaterPlanes(void);
8441
8442 static void R_Water_StartFrame(void)
8443 {
8444         int i;
8445         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8446         r_waterstate_waterplane_t *p;
8447
8448         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8449                 return;
8450
8451         switch(vid.renderpath)
8452         {
8453         case RENDERPATH_GL20:
8454         case RENDERPATH_CGGL:
8455         case RENDERPATH_D3D9:
8456         case RENDERPATH_D3D10:
8457         case RENDERPATH_D3D11:
8458                 break;
8459         case RENDERPATH_GL13:
8460         case RENDERPATH_GL11:
8461                 return;
8462         }
8463
8464         // set waterwidth and waterheight to the water resolution that will be
8465         // used (often less than the screen resolution for faster rendering)
8466         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8467         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8468
8469         // calculate desired texture sizes
8470         // can't use water if the card does not support the texture size
8471         if (!r_water.integer || r_showsurfaces.integer)
8472                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8473         else if (vid.support.arb_texture_non_power_of_two)
8474         {
8475                 texturewidth = waterwidth;
8476                 textureheight = waterheight;
8477                 camerawidth = waterwidth;
8478                 cameraheight = waterheight;
8479         }
8480         else
8481         {
8482                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8483                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8484                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8485                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8486         }
8487
8488         // allocate textures as needed
8489         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8490         {
8491                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8492                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8493                 {
8494                         if (p->texture_refraction)
8495                                 R_FreeTexture(p->texture_refraction);
8496                         p->texture_refraction = NULL;
8497                         if (p->texture_reflection)
8498                                 R_FreeTexture(p->texture_reflection);
8499                         p->texture_reflection = NULL;
8500                         if (p->texture_camera)
8501                                 R_FreeTexture(p->texture_camera);
8502                         p->texture_camera = NULL;
8503                 }
8504                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8505                 r_waterstate.texturewidth = texturewidth;
8506                 r_waterstate.textureheight = textureheight;
8507                 r_waterstate.camerawidth = camerawidth;
8508                 r_waterstate.cameraheight = cameraheight;
8509         }
8510
8511         if (r_waterstate.texturewidth)
8512         {
8513                 r_waterstate.enabled = true;
8514
8515                 // when doing a reduced render (HDR) we want to use a smaller area
8516                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8517                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8518
8519                 // set up variables that will be used in shader setup
8520                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8521                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8522                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8523                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8524         }
8525
8526         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8527         r_waterstate.numwaterplanes = 0;
8528 }
8529
8530 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8531 {
8532         int triangleindex, planeindex;
8533         const int *e;
8534         vec3_t vert[3];
8535         vec3_t normal;
8536         vec3_t center;
8537         mplane_t plane;
8538         r_waterstate_waterplane_t *p;
8539         texture_t *t = R_GetCurrentTexture(surface->texture);
8540
8541         // just use the first triangle with a valid normal for any decisions
8542         VectorClear(normal);
8543         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8544         {
8545                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8546                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8547                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8548                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8549                 if (VectorLength2(normal) >= 0.001)
8550                         break;
8551         }
8552
8553         VectorCopy(normal, plane.normal);
8554         VectorNormalize(plane.normal);
8555         plane.dist = DotProduct(vert[0], plane.normal);
8556         PlaneClassify(&plane);
8557         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8558         {
8559                 // skip backfaces (except if nocullface is set)
8560                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8561                         return;
8562                 VectorNegate(plane.normal, plane.normal);
8563                 plane.dist *= -1;
8564                 PlaneClassify(&plane);
8565         }
8566
8567
8568         // find a matching plane if there is one
8569         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8570                 if(p->camera_entity == t->camera_entity)
8571                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8572                                 break;
8573         if (planeindex >= r_waterstate.maxwaterplanes)
8574                 return; // nothing we can do, out of planes
8575
8576         // if this triangle does not fit any known plane rendered this frame, add one
8577         if (planeindex >= r_waterstate.numwaterplanes)
8578         {
8579                 // store the new plane
8580                 r_waterstate.numwaterplanes++;
8581                 p->plane = plane;
8582                 // clear materialflags and pvs
8583                 p->materialflags = 0;
8584                 p->pvsvalid = false;
8585                 p->camera_entity = t->camera_entity;
8586                 VectorCopy(surface->mins, p->mins);
8587                 VectorCopy(surface->maxs, p->maxs);
8588         }
8589         else
8590         {
8591                 // merge mins/maxs
8592                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8593                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8594                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8595                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8596                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8597                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8598         }
8599         // merge this surface's materialflags into the waterplane
8600         p->materialflags |= t->currentmaterialflags;
8601         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8602         {
8603                 // merge this surface's PVS into the waterplane
8604                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8605                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8606                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8607                 {
8608                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8609                         p->pvsvalid = true;
8610                 }
8611         }
8612 }
8613
8614 static void R_Water_ProcessPlanes(void)
8615 {
8616         int myscissor[4];
8617         r_refdef_view_t originalview;
8618         r_refdef_view_t myview;
8619         int planeindex;
8620         r_waterstate_waterplane_t *p;
8621         vec3_t visorigin;
8622
8623         originalview = r_refdef.view;
8624
8625         // make sure enough textures are allocated
8626         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8627         {
8628                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8629                 {
8630                         if (!p->texture_refraction)
8631                                 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);
8632                         if (!p->texture_refraction)
8633                                 goto error;
8634                 }
8635                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8636                 {
8637                         if (!p->texture_camera)
8638                                 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);
8639                         if (!p->texture_camera)
8640                                 goto error;
8641                 }
8642
8643                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8644                 {
8645                         if (!p->texture_reflection)
8646                                 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);
8647                         if (!p->texture_reflection)
8648                                 goto error;
8649                 }
8650         }
8651
8652         // render views
8653         r_refdef.view = originalview;
8654         r_refdef.view.showdebug = false;
8655         r_refdef.view.width = r_waterstate.waterwidth;
8656         r_refdef.view.height = r_waterstate.waterheight;
8657         r_refdef.view.useclipplane = true;
8658         myview = r_refdef.view;
8659         r_waterstate.renderingscene = true;
8660         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8661         {
8662                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8663                 {
8664                         r_refdef.view = myview;
8665                         if(r_water_scissormode.integer)
8666                         {
8667                                 R_SetupView(true);
8668                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8669                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8670                         }
8671
8672                         // render reflected scene and copy into texture
8673                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8674                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8675                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8676                         r_refdef.view.clipplane = p->plane;
8677
8678                         // reverse the cullface settings for this render
8679                         r_refdef.view.cullface_front = GL_FRONT;
8680                         r_refdef.view.cullface_back = GL_BACK;
8681                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8682                         {
8683                                 r_refdef.view.usecustompvs = true;
8684                                 if (p->pvsvalid)
8685                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8686                                 else
8687                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8688                         }
8689
8690                         R_ResetViewRendering3D();
8691                         R_ClearScreen(r_refdef.fogenabled);
8692                         if(r_water_scissormode.integer & 2)
8693                                 R_View_UpdateWithScissor(myscissor);
8694                         else
8695                                 R_View_Update();
8696                         if(r_water_scissormode.integer & 1)
8697                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8698                         R_RenderScene();
8699
8700                         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);
8701                 }
8702
8703                 // render the normal view scene and copy into texture
8704                 // (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)
8705                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8706                 {
8707                         r_refdef.view = myview;
8708                         if(r_water_scissormode.integer)
8709                         {
8710                                 R_SetupView(true);
8711                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8712                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8713                         }
8714
8715                         r_waterstate.renderingrefraction = true;
8716
8717                         r_refdef.view.clipplane = p->plane;
8718                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8719                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8720
8721                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8722                         {
8723                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8724                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8725                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8726                                 R_RenderView_UpdateViewVectors();
8727                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8728                                 {
8729                                         r_refdef.view.usecustompvs = true;
8730                                         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);
8731                                 }
8732                         }
8733
8734                         PlaneClassify(&r_refdef.view.clipplane);
8735
8736                         R_ResetViewRendering3D();
8737                         R_ClearScreen(r_refdef.fogenabled);
8738                         if(r_water_scissormode.integer & 2)
8739                                 R_View_UpdateWithScissor(myscissor);
8740                         else
8741                                 R_View_Update();
8742                         if(r_water_scissormode.integer & 1)
8743                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8744                         R_RenderScene();
8745
8746                         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);
8747                         r_waterstate.renderingrefraction = false;
8748                 }
8749                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8750                 {
8751                         r_refdef.view = myview;
8752
8753                         r_refdef.view.clipplane = p->plane;
8754                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8755                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8756
8757                         r_refdef.view.width = r_waterstate.camerawidth;
8758                         r_refdef.view.height = r_waterstate.cameraheight;
8759                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8760                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8761
8762                         if(p->camera_entity)
8763                         {
8764                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8765                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8766                         }
8767
8768                         // note: all of the view is used for displaying... so
8769                         // there is no use in scissoring
8770
8771                         // reverse the cullface settings for this render
8772                         r_refdef.view.cullface_front = GL_FRONT;
8773                         r_refdef.view.cullface_back = GL_BACK;
8774                         // also reverse the view matrix
8775                         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
8776                         R_RenderView_UpdateViewVectors();
8777                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8778                         {
8779                                 r_refdef.view.usecustompvs = true;
8780                                 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);
8781                         }
8782                         
8783                         // camera needs no clipplane
8784                         r_refdef.view.useclipplane = false;
8785
8786                         PlaneClassify(&r_refdef.view.clipplane);
8787
8788                         R_ResetViewRendering3D();
8789                         R_ClearScreen(r_refdef.fogenabled);
8790                         R_View_Update();
8791                         R_RenderScene();
8792
8793                         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);
8794                         r_waterstate.renderingrefraction = false;
8795                 }
8796
8797         }
8798         r_waterstate.renderingscene = false;
8799         r_refdef.view = originalview;
8800         R_ResetViewRendering3D();
8801         R_ClearScreen(r_refdef.fogenabled);
8802         R_View_Update();
8803         return;
8804 error:
8805         r_refdef.view = originalview;
8806         r_waterstate.renderingscene = false;
8807         Cvar_SetValueQuick(&r_water, 0);
8808         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8809         return;
8810 }
8811
8812 void R_Bloom_StartFrame(void)
8813 {
8814         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8815
8816         switch(vid.renderpath)
8817         {
8818         case RENDERPATH_GL20:
8819         case RENDERPATH_CGGL:
8820         case RENDERPATH_D3D9:
8821         case RENDERPATH_D3D10:
8822         case RENDERPATH_D3D11:
8823                 break;
8824         case RENDERPATH_GL13:
8825         case RENDERPATH_GL11:
8826                 return;
8827         }
8828
8829         // set bloomwidth and bloomheight to the bloom resolution that will be
8830         // used (often less than the screen resolution for faster rendering)
8831         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8832         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8833         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8834         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8835         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8836
8837         // calculate desired texture sizes
8838         if (vid.support.arb_texture_non_power_of_two)
8839         {
8840                 screentexturewidth = r_refdef.view.width;
8841                 screentextureheight = r_refdef.view.height;
8842                 bloomtexturewidth = r_bloomstate.bloomwidth;
8843                 bloomtextureheight = r_bloomstate.bloomheight;
8844         }
8845         else
8846         {
8847                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8848                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8849                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8850                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8851         }
8852
8853         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))
8854         {
8855                 Cvar_SetValueQuick(&r_hdr, 0);
8856                 Cvar_SetValueQuick(&r_bloom, 0);
8857                 Cvar_SetValueQuick(&r_motionblur, 0);
8858                 Cvar_SetValueQuick(&r_damageblur, 0);
8859         }
8860
8861         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)))
8862                 screentexturewidth = screentextureheight = 0;
8863         if (!r_hdr.integer && !r_bloom.integer)
8864                 bloomtexturewidth = bloomtextureheight = 0;
8865
8866         // allocate textures as needed
8867         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8868         {
8869                 if (r_bloomstate.texture_screen)
8870                         R_FreeTexture(r_bloomstate.texture_screen);
8871                 r_bloomstate.texture_screen = NULL;
8872                 r_bloomstate.screentexturewidth = screentexturewidth;
8873                 r_bloomstate.screentextureheight = screentextureheight;
8874                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8875                         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);
8876         }
8877         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8878         {
8879                 if (r_bloomstate.texture_bloom)
8880                         R_FreeTexture(r_bloomstate.texture_bloom);
8881                 r_bloomstate.texture_bloom = NULL;
8882                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8883                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8884                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8885                         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);
8886         }
8887
8888         // when doing a reduced render (HDR) we want to use a smaller area
8889         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8890         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8891         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8892         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8893         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8894
8895         // set up a texcoord array for the full resolution screen image
8896         // (we have to keep this around to copy back during final render)
8897         r_bloomstate.screentexcoord2f[0] = 0;
8898         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8899         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8900         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8901         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8902         r_bloomstate.screentexcoord2f[5] = 0;
8903         r_bloomstate.screentexcoord2f[6] = 0;
8904         r_bloomstate.screentexcoord2f[7] = 0;
8905
8906         // set up a texcoord array for the reduced resolution bloom image
8907         // (which will be additive blended over the screen image)
8908         r_bloomstate.bloomtexcoord2f[0] = 0;
8909         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8910         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8911         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8912         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8913         r_bloomstate.bloomtexcoord2f[5] = 0;
8914         r_bloomstate.bloomtexcoord2f[6] = 0;
8915         r_bloomstate.bloomtexcoord2f[7] = 0;
8916
8917         switch(vid.renderpath)
8918         {
8919         case RENDERPATH_GL11:
8920         case RENDERPATH_GL13:
8921         case RENDERPATH_GL20:
8922         case RENDERPATH_CGGL:
8923                 break;
8924         case RENDERPATH_D3D9:
8925         case RENDERPATH_D3D10:
8926         case RENDERPATH_D3D11:
8927                 {
8928                         int i;
8929                         for (i = 0;i < 4;i++)
8930                         {
8931                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8932                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8933                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8934                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8935                         }
8936                 }
8937                 break;
8938         }
8939
8940         if (r_hdr.integer || r_bloom.integer)
8941         {
8942                 r_bloomstate.enabled = true;
8943                 r_bloomstate.hdr = r_hdr.integer != 0;
8944         }
8945
8946         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);
8947 }
8948
8949 void R_Bloom_CopyBloomTexture(float colorscale)
8950 {
8951         r_refdef.stats.bloom++;
8952
8953         // scale down screen texture to the bloom texture size
8954         CHECKGLERROR
8955         R_SetViewport(&r_bloomstate.viewport);
8956         GL_BlendFunc(GL_ONE, GL_ZERO);
8957         GL_Color(colorscale, colorscale, colorscale, 1);
8958         // 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...
8959         switch(vid.renderpath)
8960         {
8961         case RENDERPATH_GL11:
8962         case RENDERPATH_GL13:
8963         case RENDERPATH_GL20:
8964         case RENDERPATH_CGGL:
8965                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8966                 break;
8967         case RENDERPATH_D3D9:
8968         case RENDERPATH_D3D10:
8969         case RENDERPATH_D3D11:
8970                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8971                 break;
8972         }
8973         // TODO: do boxfilter scale-down in shader?
8974         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8975         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8976         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8977
8978         // we now have a bloom image in the framebuffer
8979         // copy it into the bloom image texture for later processing
8980         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);
8981         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8982 }
8983
8984 void R_Bloom_CopyHDRTexture(void)
8985 {
8986         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);
8987         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8988 }
8989
8990 void R_Bloom_MakeTexture(void)
8991 {
8992         int x, range, dir;
8993         float xoffset, yoffset, r, brighten;
8994
8995         r_refdef.stats.bloom++;
8996
8997         R_ResetViewRendering2D();
8998
8999         // we have a bloom image in the framebuffer
9000         CHECKGLERROR
9001         R_SetViewport(&r_bloomstate.viewport);
9002
9003         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9004         {
9005                 x *= 2;
9006                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9007                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9008                 GL_Color(r,r,r,1);
9009                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9010                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9011                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9012                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9013
9014                 // copy the vertically blurred bloom view to a texture
9015                 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);
9016                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9017         }
9018
9019         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9020         brighten = r_bloom_brighten.value;
9021         if (r_hdr.integer)
9022                 brighten *= r_hdr_range.value;
9023         brighten = sqrt(brighten);
9024         if(range >= 1)
9025                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9026         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9027
9028         for (dir = 0;dir < 2;dir++)
9029         {
9030                 // blend on at multiple vertical offsets to achieve a vertical blur
9031                 // TODO: do offset blends using GLSL
9032                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9033                 GL_BlendFunc(GL_ONE, GL_ZERO);
9034                 for (x = -range;x <= range;x++)
9035                 {
9036                         if (!dir){xoffset = 0;yoffset = x;}
9037                         else {xoffset = x;yoffset = 0;}
9038                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9039                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9040                         // compute a texcoord array with the specified x and y offset
9041                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9042                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9043                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9044                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9045                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9046                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9047                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9048                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9049                         // this r value looks like a 'dot' particle, fading sharply to
9050                         // black at the edges
9051                         // (probably not realistic but looks good enough)
9052                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9053                         //r = brighten/(range*2+1);
9054                         r = brighten / (range * 2 + 1);
9055                         if(range >= 1)
9056                                 r *= (1 - x*x/(float)(range*range));
9057                         GL_Color(r, r, r, 1);
9058                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9059                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9060                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9061                         GL_BlendFunc(GL_ONE, GL_ONE);
9062                 }
9063
9064                 // copy the vertically blurred bloom view to a texture
9065                 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);
9066                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9067         }
9068 }
9069
9070 void R_HDR_RenderBloomTexture(void)
9071 {
9072         int oldwidth, oldheight;
9073         float oldcolorscale;
9074
9075         oldcolorscale = r_refdef.view.colorscale;
9076         oldwidth = r_refdef.view.width;
9077         oldheight = r_refdef.view.height;
9078         r_refdef.view.width = r_bloomstate.bloomwidth;
9079         r_refdef.view.height = r_bloomstate.bloomheight;
9080
9081         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9082         // TODO: add exposure compensation features
9083         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9084
9085         r_refdef.view.showdebug = false;
9086         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9087
9088         R_ResetViewRendering3D();
9089
9090         R_ClearScreen(r_refdef.fogenabled);
9091         if (r_timereport_active)
9092                 R_TimeReport("HDRclear");
9093
9094         R_View_Update();
9095         if (r_timereport_active)
9096                 R_TimeReport("visibility");
9097
9098         // only do secondary renders with HDR if r_hdr is 2 or higher
9099         r_waterstate.numwaterplanes = 0;
9100         if (r_waterstate.enabled && r_hdr.integer >= 2)
9101                 R_RenderWaterPlanes();
9102
9103         r_refdef.view.showdebug = true;
9104         R_RenderScene();
9105         r_waterstate.numwaterplanes = 0;
9106
9107         R_ResetViewRendering2D();
9108
9109         R_Bloom_CopyHDRTexture();
9110         R_Bloom_MakeTexture();
9111
9112         // restore the view settings
9113         r_refdef.view.width = oldwidth;
9114         r_refdef.view.height = oldheight;
9115         r_refdef.view.colorscale = oldcolorscale;
9116
9117         R_ResetViewRendering3D();
9118
9119         R_ClearScreen(r_refdef.fogenabled);
9120         if (r_timereport_active)
9121                 R_TimeReport("viewclear");
9122 }
9123
9124 static void R_BlendView(void)
9125 {
9126         unsigned int permutation;
9127         float uservecs[4][4];
9128
9129         switch (vid.renderpath)
9130         {
9131         case RENDERPATH_GL20:
9132         case RENDERPATH_CGGL:
9133         case RENDERPATH_D3D9:
9134         case RENDERPATH_D3D10:
9135         case RENDERPATH_D3D11:
9136                 permutation =
9137                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9138                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9139                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9140                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9141                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9142
9143                 if (r_bloomstate.texture_screen)
9144                 {
9145                         // make sure the buffer is available
9146                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9147
9148                         R_ResetViewRendering2D();
9149
9150                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9151                         {
9152                                 // declare variables
9153                                 float speed;
9154                                 static float avgspeed;
9155
9156                                 speed = VectorLength(cl.movement_velocity);
9157
9158                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9159                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9160
9161                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9162                                 speed = bound(0, speed, 1);
9163                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9164
9165                                 // calculate values into a standard alpha
9166                                 cl.motionbluralpha = 1 - exp(-
9167                                                 (
9168                                                  (r_motionblur.value * speed / 80)
9169                                                  +
9170                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9171                                                 )
9172                                                 /
9173                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9174                                            );
9175
9176                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9177                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9178                                 // apply the blur
9179                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9180                                 {
9181                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9182                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9183                                         switch(vid.renderpath)
9184                                         {
9185                                         case RENDERPATH_GL11:
9186                                         case RENDERPATH_GL13:
9187                                         case RENDERPATH_GL20:
9188                                         case RENDERPATH_CGGL:
9189                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9190                                                 break;
9191                                         case RENDERPATH_D3D9:
9192                                         case RENDERPATH_D3D10:
9193                                         case RENDERPATH_D3D11:
9194                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9195                                                 break;
9196                                         }
9197                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9198                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9199                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9200                                 }
9201                         }
9202
9203                         // copy view into the screen texture
9204                         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);
9205                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9206                 }
9207                 else if (!r_bloomstate.texture_bloom)
9208                 {
9209                         // we may still have to do view tint...
9210                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9211                         {
9212                                 // apply a color tint to the whole view
9213                                 R_ResetViewRendering2D();
9214                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9215                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9216                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9217                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9218                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9219                         }
9220                         break; // no screen processing, no bloom, skip it
9221                 }
9222
9223                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9224                 {
9225                         // render simple bloom effect
9226                         // copy the screen and shrink it and darken it for the bloom process
9227                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9228                         // make the bloom texture
9229                         R_Bloom_MakeTexture();
9230                 }
9231
9232 #if _MSC_VER >= 1400
9233 #define sscanf sscanf_s
9234 #endif
9235                 memset(uservecs, 0, sizeof(uservecs));
9236                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9237                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9238                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9239                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9240
9241                 R_ResetViewRendering2D();
9242                 GL_Color(1, 1, 1, 1);
9243                 GL_BlendFunc(GL_ONE, GL_ZERO);
9244
9245                 switch(vid.renderpath)
9246                 {
9247                 case RENDERPATH_GL20:
9248                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9249                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9250                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9251                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9252                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9253                         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]);
9254                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9255                         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]);
9256                         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]);
9257                         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]);
9258                         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]);
9259                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9260                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9261                         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);
9262                         break;
9263                 case RENDERPATH_CGGL:
9264 #ifdef SUPPORTCG
9265                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9266                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9267                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9268                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9269                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9270                         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
9271                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9272                         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
9273                         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
9274                         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
9275                         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
9276                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9277                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9278                         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);
9279 #endif
9280                         break;
9281                 case RENDERPATH_D3D9:
9282 #ifdef SUPPORTD3D
9283                         // 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...
9284                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9285                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9286                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9287                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9288                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9289                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9290                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9291                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9292                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9293                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9294                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9295                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9296                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9297                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9298 #endif
9299                         break;
9300                 case RENDERPATH_D3D10:
9301                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9302                         break;
9303                 case RENDERPATH_D3D11:
9304                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9305                         break;
9306                 default:
9307                         break;
9308                 }
9309                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9310                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9311                 break;
9312         case RENDERPATH_GL13:
9313         case RENDERPATH_GL11:
9314                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9315                 {
9316                         // apply a color tint to the whole view
9317                         R_ResetViewRendering2D();
9318                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9319                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9320                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9321                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9322                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9323                 }
9324                 break;
9325         }
9326 }
9327
9328 matrix4x4_t r_waterscrollmatrix;
9329
9330 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9331 {
9332         if (r_refdef.fog_density)
9333         {
9334                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9335                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9336                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9337
9338                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9339                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9340                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9341                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9342
9343                 {
9344                         vec3_t fogvec;
9345                         VectorCopy(r_refdef.fogcolor, fogvec);
9346                         //   color.rgb *= ContrastBoost * SceneBrightness;
9347                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9348                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9349                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9350                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9351                 }
9352         }
9353 }
9354
9355 void R_UpdateVariables(void)
9356 {
9357         R_Textures_Frame();
9358
9359         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9360
9361         r_refdef.farclip = r_farclip_base.value;
9362         if (r_refdef.scene.worldmodel)
9363                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9364         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9365
9366         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9367                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9368         r_refdef.polygonfactor = 0;
9369         r_refdef.polygonoffset = 0;
9370         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9371         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9372
9373         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9374         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9375         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9376         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9377         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9378         if (FAKELIGHT_ENABLED)
9379         {
9380                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9381         }
9382         if (r_showsurfaces.integer)
9383         {
9384                 r_refdef.scene.rtworld = false;
9385                 r_refdef.scene.rtworldshadows = false;
9386                 r_refdef.scene.rtdlight = false;
9387                 r_refdef.scene.rtdlightshadows = false;
9388                 r_refdef.lightmapintensity = 0;
9389         }
9390
9391         if (gamemode == GAME_NEHAHRA)
9392         {
9393                 if (gl_fogenable.integer)
9394                 {
9395                         r_refdef.oldgl_fogenable = true;
9396                         r_refdef.fog_density = gl_fogdensity.value;
9397                         r_refdef.fog_red = gl_fogred.value;
9398                         r_refdef.fog_green = gl_foggreen.value;
9399                         r_refdef.fog_blue = gl_fogblue.value;
9400                         r_refdef.fog_alpha = 1;
9401                         r_refdef.fog_start = 0;
9402                         r_refdef.fog_end = gl_skyclip.value;
9403                         r_refdef.fog_height = 1<<30;
9404                         r_refdef.fog_fadedepth = 128;
9405                 }
9406                 else if (r_refdef.oldgl_fogenable)
9407                 {
9408                         r_refdef.oldgl_fogenable = false;
9409                         r_refdef.fog_density = 0;
9410                         r_refdef.fog_red = 0;
9411                         r_refdef.fog_green = 0;
9412                         r_refdef.fog_blue = 0;
9413                         r_refdef.fog_alpha = 0;
9414                         r_refdef.fog_start = 0;
9415                         r_refdef.fog_end = 0;
9416                         r_refdef.fog_height = 1<<30;
9417                         r_refdef.fog_fadedepth = 128;
9418                 }
9419         }
9420
9421         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9422         r_refdef.fog_start = max(0, r_refdef.fog_start);
9423         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9424
9425         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9426
9427         if (r_refdef.fog_density && r_drawfog.integer)
9428         {
9429                 r_refdef.fogenabled = true;
9430                 // this is the point where the fog reaches 0.9986 alpha, which we
9431                 // consider a good enough cutoff point for the texture
9432                 // (0.9986 * 256 == 255.6)
9433                 if (r_fog_exp2.integer)
9434                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9435                 else
9436                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9437                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9438                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9439                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9440                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9441                         R_BuildFogHeightTexture();
9442                 // fog color was already set
9443                 // update the fog texture
9444                 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)
9445                         R_BuildFogTexture();
9446                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9447                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9448         }
9449         else
9450                 r_refdef.fogenabled = false;
9451
9452         switch(vid.renderpath)
9453         {
9454         case RENDERPATH_GL20:
9455         case RENDERPATH_CGGL:
9456         case RENDERPATH_D3D9:
9457         case RENDERPATH_D3D10:
9458         case RENDERPATH_D3D11:
9459                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9460                 {
9461                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9462                         {
9463                                 // build GLSL gamma texture
9464 #define RAMPWIDTH 256
9465                                 unsigned short ramp[RAMPWIDTH * 3];
9466                                 unsigned char rampbgr[RAMPWIDTH][4];
9467                                 int i;
9468
9469                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9470
9471                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9472                                 for(i = 0; i < RAMPWIDTH; ++i)
9473                                 {
9474                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9475                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9476                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9477                                         rampbgr[i][3] = 0;
9478                                 }
9479                                 if (r_texture_gammaramps)
9480                                 {
9481                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9482                                 }
9483                                 else
9484                                 {
9485                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9486                                 }
9487                         }
9488                 }
9489                 else
9490                 {
9491                         // remove GLSL gamma texture
9492                 }
9493                 break;
9494         case RENDERPATH_GL13:
9495         case RENDERPATH_GL11:
9496                 break;
9497         }
9498 }
9499
9500 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9501 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9502 /*
9503 ================
9504 R_SelectScene
9505 ================
9506 */
9507 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9508         if( scenetype != r_currentscenetype ) {
9509                 // store the old scenetype
9510                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9511                 r_currentscenetype = scenetype;
9512                 // move in the new scene
9513                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9514         }
9515 }
9516
9517 /*
9518 ================
9519 R_GetScenePointer
9520 ================
9521 */
9522 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9523 {
9524         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9525         if( scenetype == r_currentscenetype ) {
9526                 return &r_refdef.scene;
9527         } else {
9528                 return &r_scenes_store[ scenetype ];
9529         }
9530 }
9531
9532 /*
9533 ================
9534 R_RenderView
9535 ================
9536 */
9537 void R_RenderView(void)
9538 {
9539         if (r_timereport_active)
9540                 R_TimeReport("start");
9541         r_textureframe++; // used only by R_GetCurrentTexture
9542         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9543
9544         if (!r_drawentities.integer)
9545                 r_refdef.scene.numentities = 0;
9546
9547         R_AnimCache_ClearCache();
9548         R_FrameData_NewFrame();
9549
9550         if (r_refdef.view.isoverlay)
9551         {
9552                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9553                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9554                 R_TimeReport("depthclear");
9555
9556                 r_refdef.view.showdebug = false;
9557
9558                 r_waterstate.enabled = false;
9559                 r_waterstate.numwaterplanes = 0;
9560
9561                 R_RenderScene();
9562
9563                 CHECKGLERROR
9564                 return;
9565         }
9566
9567         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9568                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9569
9570         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9571
9572         R_RenderView_UpdateViewVectors();
9573
9574         R_Shadow_UpdateWorldLightSelection();
9575
9576         R_Bloom_StartFrame();
9577         R_Water_StartFrame();
9578
9579         CHECKGLERROR
9580         if (r_timereport_active)
9581                 R_TimeReport("viewsetup");
9582
9583         R_ResetViewRendering3D();
9584
9585         if (r_refdef.view.clear || r_refdef.fogenabled)
9586         {
9587                 R_ClearScreen(r_refdef.fogenabled);
9588                 if (r_timereport_active)
9589                         R_TimeReport("viewclear");
9590         }
9591         r_refdef.view.clear = true;
9592
9593         // this produces a bloom texture to be used in R_BlendView() later
9594         if (r_hdr.integer && r_bloomstate.bloomwidth)
9595         {
9596                 R_HDR_RenderBloomTexture();
9597                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9598                 r_textureframe++; // used only by R_GetCurrentTexture
9599         }
9600
9601         r_refdef.view.showdebug = true;
9602
9603         R_View_Update();
9604         if (r_timereport_active)
9605                 R_TimeReport("visibility");
9606
9607         r_waterstate.numwaterplanes = 0;
9608         if (r_waterstate.enabled)
9609                 R_RenderWaterPlanes();
9610
9611         R_RenderScene();
9612         r_waterstate.numwaterplanes = 0;
9613
9614         R_BlendView();
9615         if (r_timereport_active)
9616                 R_TimeReport("blendview");
9617
9618         GL_Scissor(0, 0, vid.width, vid.height);
9619         GL_ScissorTest(false);
9620
9621         CHECKGLERROR
9622 }
9623
9624 void R_RenderWaterPlanes(void)
9625 {
9626         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9627         {
9628                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9629                 if (r_timereport_active)
9630                         R_TimeReport("waterworld");
9631         }
9632
9633         // don't let sound skip if going slow
9634         if (r_refdef.scene.extraupdate)
9635                 S_ExtraUpdate ();
9636
9637         R_DrawModelsAddWaterPlanes();
9638         if (r_timereport_active)
9639                 R_TimeReport("watermodels");
9640
9641         if (r_waterstate.numwaterplanes)
9642         {
9643                 R_Water_ProcessPlanes();
9644                 if (r_timereport_active)
9645                         R_TimeReport("waterscenes");
9646         }
9647 }
9648
9649 extern void R_DrawLightningBeams (void);
9650 extern void VM_CL_AddPolygonsToMeshQueue (void);
9651 extern void R_DrawPortals (void);
9652 extern cvar_t cl_locs_show;
9653 static void R_DrawLocs(void);
9654 static void R_DrawEntityBBoxes(void);
9655 static void R_DrawModelDecals(void);
9656 extern void R_DrawModelShadows(void);
9657 extern void R_DrawModelShadowMaps(void);
9658 extern cvar_t cl_decals_newsystem;
9659 extern qboolean r_shadow_usingdeferredprepass;
9660 void R_RenderScene(void)
9661 {
9662         qboolean shadowmapping = false;
9663
9664         if (r_timereport_active)
9665                 R_TimeReport("beginscene");
9666
9667         r_refdef.stats.renders++;
9668
9669         R_UpdateFogColor();
9670
9671         // don't let sound skip if going slow
9672         if (r_refdef.scene.extraupdate)
9673                 S_ExtraUpdate ();
9674
9675         R_MeshQueue_BeginScene();
9676
9677         R_SkyStartFrame();
9678
9679         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);
9680
9681         if (r_timereport_active)
9682                 R_TimeReport("skystartframe");
9683
9684         if (cl.csqc_vidvars.drawworld)
9685         {
9686                 // don't let sound skip if going slow
9687                 if (r_refdef.scene.extraupdate)
9688                         S_ExtraUpdate ();
9689
9690                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9691                 {
9692                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9693                         if (r_timereport_active)
9694                                 R_TimeReport("worldsky");
9695                 }
9696
9697                 if (R_DrawBrushModelsSky() && r_timereport_active)
9698                         R_TimeReport("bmodelsky");
9699
9700                 if (skyrendermasked && skyrenderlater)
9701                 {
9702                         // we have to force off the water clipping plane while rendering sky
9703                         R_SetupView(false);
9704                         R_Sky();
9705                         R_SetupView(true);
9706                         if (r_timereport_active)
9707                                 R_TimeReport("sky");
9708                 }
9709         }
9710
9711         R_AnimCache_CacheVisibleEntities();
9712         if (r_timereport_active)
9713                 R_TimeReport("animation");
9714
9715         R_Shadow_PrepareLights();
9716         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9717                 R_Shadow_PrepareModelShadows();
9718         if (r_timereport_active)
9719                 R_TimeReport("preparelights");
9720
9721         if (R_Shadow_ShadowMappingEnabled())
9722                 shadowmapping = true;
9723
9724         if (r_shadow_usingdeferredprepass)
9725                 R_Shadow_DrawPrepass();
9726
9727         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9728         {
9729                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9730                 if (r_timereport_active)
9731                         R_TimeReport("worlddepth");
9732         }
9733         if (r_depthfirst.integer >= 2)
9734         {
9735                 R_DrawModelsDepth();
9736                 if (r_timereport_active)
9737                         R_TimeReport("modeldepth");
9738         }
9739
9740         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9741         {
9742                 R_DrawModelShadowMaps();
9743                 R_ResetViewRendering3D();
9744                 // don't let sound skip if going slow
9745                 if (r_refdef.scene.extraupdate)
9746                         S_ExtraUpdate ();
9747         }
9748
9749         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9750         {
9751                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9752                 if (r_timereport_active)
9753                         R_TimeReport("world");
9754         }
9755
9756         // don't let sound skip if going slow
9757         if (r_refdef.scene.extraupdate)
9758                 S_ExtraUpdate ();
9759
9760         R_DrawModels();
9761         if (r_timereport_active)
9762                 R_TimeReport("models");
9763
9764         // don't let sound skip if going slow
9765         if (r_refdef.scene.extraupdate)
9766                 S_ExtraUpdate ();
9767
9768         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9769         {
9770                 R_DrawModelShadows();
9771                 R_ResetViewRendering3D();
9772                 // don't let sound skip if going slow
9773                 if (r_refdef.scene.extraupdate)
9774                         S_ExtraUpdate ();
9775         }
9776
9777         if (!r_shadow_usingdeferredprepass)
9778         {
9779                 R_Shadow_DrawLights();
9780                 if (r_timereport_active)
9781                         R_TimeReport("rtlights");
9782         }
9783
9784         // don't let sound skip if going slow
9785         if (r_refdef.scene.extraupdate)
9786                 S_ExtraUpdate ();
9787
9788         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9789         {
9790                 R_DrawModelShadows();
9791                 R_ResetViewRendering3D();
9792                 // don't let sound skip if going slow
9793                 if (r_refdef.scene.extraupdate)
9794                         S_ExtraUpdate ();
9795         }
9796
9797         if (cl.csqc_vidvars.drawworld)
9798         {
9799                 if (cl_decals_newsystem.integer)
9800                 {
9801                         R_DrawModelDecals();
9802                         if (r_timereport_active)
9803                                 R_TimeReport("modeldecals");
9804                 }
9805                 else
9806                 {
9807                         R_DrawDecals();
9808                         if (r_timereport_active)
9809                                 R_TimeReport("decals");
9810                 }
9811
9812                 R_DrawParticles();
9813                 if (r_timereport_active)
9814                         R_TimeReport("particles");
9815
9816                 R_DrawExplosions();
9817                 if (r_timereport_active)
9818                         R_TimeReport("explosions");
9819
9820                 R_DrawLightningBeams();
9821                 if (r_timereport_active)
9822                         R_TimeReport("lightning");
9823         }
9824
9825         VM_CL_AddPolygonsToMeshQueue();
9826
9827         if (r_refdef.view.showdebug)
9828         {
9829                 if (cl_locs_show.integer)
9830                 {
9831                         R_DrawLocs();
9832                         if (r_timereport_active)
9833                                 R_TimeReport("showlocs");
9834                 }
9835
9836                 if (r_drawportals.integer)
9837                 {
9838                         R_DrawPortals();
9839                         if (r_timereport_active)
9840                                 R_TimeReport("portals");
9841                 }
9842
9843                 if (r_showbboxes.value > 0)
9844                 {
9845                         R_DrawEntityBBoxes();
9846                         if (r_timereport_active)
9847                                 R_TimeReport("bboxes");
9848                 }
9849         }
9850
9851         R_MeshQueue_RenderTransparent();
9852         if (r_timereport_active)
9853                 R_TimeReport("drawtrans");
9854
9855         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))
9856         {
9857                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9858                 if (r_timereport_active)
9859                         R_TimeReport("worlddebug");
9860                 R_DrawModelsDebug();
9861                 if (r_timereport_active)
9862                         R_TimeReport("modeldebug");
9863         }
9864
9865         if (cl.csqc_vidvars.drawworld)
9866         {
9867                 R_Shadow_DrawCoronas();
9868                 if (r_timereport_active)
9869                         R_TimeReport("coronas");
9870         }
9871
9872 #if 0
9873         {
9874                 GL_DepthTest(false);
9875                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9876                 GL_Color(1, 1, 1, 1);
9877                 qglBegin(GL_POLYGON);
9878                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9879                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9880                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9881                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9882                 qglEnd();
9883                 qglBegin(GL_POLYGON);
9884                 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]);
9885                 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]);
9886                 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]);
9887                 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]);
9888                 qglEnd();
9889                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9890         }
9891 #endif
9892
9893         // don't let sound skip if going slow
9894         if (r_refdef.scene.extraupdate)
9895                 S_ExtraUpdate ();
9896
9897         R_ResetViewRendering2D();
9898 }
9899
9900 static const unsigned short bboxelements[36] =
9901 {
9902         5, 1, 3, 5, 3, 7,
9903         6, 2, 0, 6, 0, 4,
9904         7, 3, 2, 7, 2, 6,
9905         4, 0, 1, 4, 1, 5,
9906         4, 5, 7, 4, 7, 6,
9907         1, 0, 2, 1, 2, 3,
9908 };
9909
9910 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9911 {
9912         int i;
9913         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9914
9915         RSurf_ActiveWorldEntity();
9916
9917         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9918         GL_DepthMask(false);
9919         GL_DepthRange(0, 1);
9920         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9921         R_Mesh_ResetTextureState();
9922
9923         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9924         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9925         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9926         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9927         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9928         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9929         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9930         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9931         R_FillColors(color4f, 8, cr, cg, cb, ca);
9932         if (r_refdef.fogenabled)
9933         {
9934                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9935                 {
9936                         f1 = RSurf_FogVertex(v);
9937                         f2 = 1 - f1;
9938                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9939                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9940                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9941                 }
9942         }
9943         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9944         R_Mesh_ResetTextureState();
9945         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9946         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9947 }
9948
9949 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9950 {
9951         int i;
9952         float color[4];
9953         prvm_edict_t *edict;
9954         prvm_prog_t *prog_save = prog;
9955
9956         // this function draws bounding boxes of server entities
9957         if (!sv.active)
9958                 return;
9959
9960         GL_CullFace(GL_NONE);
9961         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9962
9963         prog = 0;
9964         SV_VM_Begin();
9965         for (i = 0;i < numsurfaces;i++)
9966         {
9967                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9968                 switch ((int)edict->fields.server->solid)
9969                 {
9970                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9971                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9972                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9973                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9974                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9975                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9976                 }
9977                 color[3] *= r_showbboxes.value;
9978                 color[3] = bound(0, color[3], 1);
9979                 GL_DepthTest(!r_showdisabledepthtest.integer);
9980                 GL_CullFace(r_refdef.view.cullface_front);
9981                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9982         }
9983         SV_VM_End();
9984         prog = prog_save;
9985 }
9986
9987 static void R_DrawEntityBBoxes(void)
9988 {
9989         int i;
9990         prvm_edict_t *edict;
9991         vec3_t center;
9992         prvm_prog_t *prog_save = prog;
9993
9994         // this function draws bounding boxes of server entities
9995         if (!sv.active)
9996                 return;
9997
9998         prog = 0;
9999         SV_VM_Begin();
10000         for (i = 0;i < prog->num_edicts;i++)
10001         {
10002                 edict = PRVM_EDICT_NUM(i);
10003                 if (edict->priv.server->free)
10004                         continue;
10005                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10006                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10007                         continue;
10008                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10009                         continue;
10010                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10011                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10012         }
10013         SV_VM_End();
10014         prog = prog_save;
10015 }
10016
10017 static const int nomodelelement3i[24] =
10018 {
10019         5, 2, 0,
10020         5, 1, 2,
10021         5, 0, 3,
10022         5, 3, 1,
10023         0, 2, 4,
10024         2, 1, 4,
10025         3, 0, 4,
10026         1, 3, 4
10027 };
10028
10029 static const unsigned short nomodelelement3s[24] =
10030 {
10031         5, 2, 0,
10032         5, 1, 2,
10033         5, 0, 3,
10034         5, 3, 1,
10035         0, 2, 4,
10036         2, 1, 4,
10037         3, 0, 4,
10038         1, 3, 4
10039 };
10040
10041 static const float nomodelvertex3f[6*3] =
10042 {
10043         -16,   0,   0,
10044          16,   0,   0,
10045           0, -16,   0,
10046           0,  16,   0,
10047           0,   0, -16,
10048           0,   0,  16
10049 };
10050
10051 static const float nomodelcolor4f[6*4] =
10052 {
10053         0.0f, 0.0f, 0.5f, 1.0f,
10054         0.0f, 0.0f, 0.5f, 1.0f,
10055         0.0f, 0.5f, 0.0f, 1.0f,
10056         0.0f, 0.5f, 0.0f, 1.0f,
10057         0.5f, 0.0f, 0.0f, 1.0f,
10058         0.5f, 0.0f, 0.0f, 1.0f
10059 };
10060
10061 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10062 {
10063         int i;
10064         float f1, f2, *c;
10065         float color4f[6*4];
10066
10067         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);
10068
10069         // this is only called once per entity so numsurfaces is always 1, and
10070         // surfacelist is always {0}, so this code does not handle batches
10071
10072         if (rsurface.ent_flags & RENDER_ADDITIVE)
10073         {
10074                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10075                 GL_DepthMask(false);
10076         }
10077         else if (rsurface.colormod[3] < 1)
10078         {
10079                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10080                 GL_DepthMask(false);
10081         }
10082         else
10083         {
10084                 GL_BlendFunc(GL_ONE, GL_ZERO);
10085                 GL_DepthMask(true);
10086         }
10087         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10088         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10089         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10090         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10091         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10092         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10093         for (i = 0, c = color4f;i < 6;i++, c += 4)
10094         {
10095                 c[0] *= rsurface.colormod[0];
10096                 c[1] *= rsurface.colormod[1];
10097                 c[2] *= rsurface.colormod[2];
10098                 c[3] *= rsurface.colormod[3];
10099         }
10100         if (r_refdef.fogenabled)
10101         {
10102                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10103                 {
10104                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10105                         f2 = 1 - f1;
10106                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10107                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10108                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10109                 }
10110         }
10111         R_Mesh_ResetTextureState();
10112         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10113         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10114 }
10115
10116 void R_DrawNoModel(entity_render_t *ent)
10117 {
10118         vec3_t org;
10119         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10120         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10121                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10122         else
10123                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10124 }
10125
10126 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10127 {
10128         vec3_t right1, right2, diff, normal;
10129
10130         VectorSubtract (org2, org1, normal);
10131
10132         // calculate 'right' vector for start
10133         VectorSubtract (r_refdef.view.origin, org1, diff);
10134         CrossProduct (normal, diff, right1);
10135         VectorNormalize (right1);
10136
10137         // calculate 'right' vector for end
10138         VectorSubtract (r_refdef.view.origin, org2, diff);
10139         CrossProduct (normal, diff, right2);
10140         VectorNormalize (right2);
10141
10142         vert[ 0] = org1[0] + width * right1[0];
10143         vert[ 1] = org1[1] + width * right1[1];
10144         vert[ 2] = org1[2] + width * right1[2];
10145         vert[ 3] = org1[0] - width * right1[0];
10146         vert[ 4] = org1[1] - width * right1[1];
10147         vert[ 5] = org1[2] - width * right1[2];
10148         vert[ 6] = org2[0] - width * right2[0];
10149         vert[ 7] = org2[1] - width * right2[1];
10150         vert[ 8] = org2[2] - width * right2[2];
10151         vert[ 9] = org2[0] + width * right2[0];
10152         vert[10] = org2[1] + width * right2[1];
10153         vert[11] = org2[2] + width * right2[2];
10154 }
10155
10156 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)
10157 {
10158         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10159         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10160         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10161         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10162         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10163         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10164         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10165         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10166         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10167         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10168         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10169         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10170 }
10171
10172 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10173 {
10174         int i;
10175         float *vertex3f;
10176         float v[3];
10177         VectorSet(v, x, y, z);
10178         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10179                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10180                         break;
10181         if (i == mesh->numvertices)
10182         {
10183                 if (mesh->numvertices < mesh->maxvertices)
10184                 {
10185                         VectorCopy(v, vertex3f);
10186                         mesh->numvertices++;
10187                 }
10188                 return mesh->numvertices;
10189         }
10190         else
10191                 return i;
10192 }
10193
10194 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10195 {
10196         int i;
10197         int *e, element[3];
10198         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10199         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10200         e = mesh->element3i + mesh->numtriangles * 3;
10201         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10202         {
10203                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10204                 if (mesh->numtriangles < mesh->maxtriangles)
10205                 {
10206                         *e++ = element[0];
10207                         *e++ = element[1];
10208                         *e++ = element[2];
10209                         mesh->numtriangles++;
10210                 }
10211                 element[1] = element[2];
10212         }
10213 }
10214
10215 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10216 {
10217         int i;
10218         int *e, element[3];
10219         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10220         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10221         e = mesh->element3i + mesh->numtriangles * 3;
10222         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10223         {
10224                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10225                 if (mesh->numtriangles < mesh->maxtriangles)
10226                 {
10227                         *e++ = element[0];
10228                         *e++ = element[1];
10229                         *e++ = element[2];
10230                         mesh->numtriangles++;
10231                 }
10232                 element[1] = element[2];
10233         }
10234 }
10235
10236 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10237 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10238 {
10239         int planenum, planenum2;
10240         int w;
10241         int tempnumpoints;
10242         mplane_t *plane, *plane2;
10243         double maxdist;
10244         double temppoints[2][256*3];
10245         // figure out how large a bounding box we need to properly compute this brush
10246         maxdist = 0;
10247         for (w = 0;w < numplanes;w++)
10248                 maxdist = max(maxdist, fabs(planes[w].dist));
10249         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10250         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10251         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10252         {
10253                 w = 0;
10254                 tempnumpoints = 4;
10255                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10256                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10257                 {
10258                         if (planenum2 == planenum)
10259                                 continue;
10260                         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);
10261                         w = !w;
10262                 }
10263                 if (tempnumpoints < 3)
10264                         continue;
10265                 // generate elements forming a triangle fan for this polygon
10266                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10267         }
10268 }
10269
10270 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)
10271 {
10272         texturelayer_t *layer;
10273         layer = t->currentlayers + t->currentnumlayers++;
10274         layer->type = type;
10275         layer->depthmask = depthmask;
10276         layer->blendfunc1 = blendfunc1;
10277         layer->blendfunc2 = blendfunc2;
10278         layer->texture = texture;
10279         layer->texmatrix = *matrix;
10280         layer->color[0] = r;
10281         layer->color[1] = g;
10282         layer->color[2] = b;
10283         layer->color[3] = a;
10284 }
10285
10286 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10287 {
10288         if(parms[0] == 0 && parms[1] == 0)
10289                 return false;
10290         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10291                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10292                         return false;
10293         return true;
10294 }
10295
10296 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10297 {
10298         double index, f;
10299         index = parms[2] + r_refdef.scene.time * parms[3];
10300         index -= floor(index);
10301         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10302         {
10303         default:
10304         case Q3WAVEFUNC_NONE:
10305         case Q3WAVEFUNC_NOISE:
10306         case Q3WAVEFUNC_COUNT:
10307                 f = 0;
10308                 break;
10309         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10310         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10311         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10312         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10313         case Q3WAVEFUNC_TRIANGLE:
10314                 index *= 4;
10315                 f = index - floor(index);
10316                 if (index < 1)
10317                         f = f;
10318                 else if (index < 2)
10319                         f = 1 - f;
10320                 else if (index < 3)
10321                         f = -f;
10322                 else
10323                         f = -(1 - f);
10324                 break;
10325         }
10326         f = parms[0] + parms[1] * f;
10327         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10328                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10329         return (float) f;
10330 }
10331
10332 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10333 {
10334         int w, h, idx;
10335         float f;
10336         float tcmat[12];
10337         matrix4x4_t matrix, temp;
10338         switch(tcmod->tcmod)
10339         {
10340                 case Q3TCMOD_COUNT:
10341                 case Q3TCMOD_NONE:
10342                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10343                                 matrix = r_waterscrollmatrix;
10344                         else
10345                                 matrix = identitymatrix;
10346                         break;
10347                 case Q3TCMOD_ENTITYTRANSLATE:
10348                         // this is used in Q3 to allow the gamecode to control texcoord
10349                         // scrolling on the entity, which is not supported in darkplaces yet.
10350                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10351                         break;
10352                 case Q3TCMOD_ROTATE:
10353                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10354                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10355                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10356                         break;
10357                 case Q3TCMOD_SCALE:
10358                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10359                         break;
10360                 case Q3TCMOD_SCROLL:
10361                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10362                         break;
10363                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10364                         w = (int) tcmod->parms[0];
10365                         h = (int) tcmod->parms[1];
10366                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10367                         f = f - floor(f);
10368                         idx = (int) floor(f * w * h);
10369                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10370                         break;
10371                 case Q3TCMOD_STRETCH:
10372                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10373                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10374                         break;
10375                 case Q3TCMOD_TRANSFORM:
10376                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10377                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10378                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10379                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10380                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10381                         break;
10382                 case Q3TCMOD_TURBULENT:
10383                         // this is handled in the RSurf_PrepareVertices function
10384                         matrix = identitymatrix;
10385                         break;
10386         }
10387         temp = *texmatrix;
10388         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10389 }
10390
10391 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10392 {
10393         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10394         char name[MAX_QPATH];
10395         skinframe_t *skinframe;
10396         unsigned char pixels[296*194];
10397         strlcpy(cache->name, skinname, sizeof(cache->name));
10398         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10399         if (developer_loading.integer)
10400                 Con_Printf("loading %s\n", name);
10401         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10402         if (!skinframe || !skinframe->base)
10403         {
10404                 unsigned char *f;
10405                 fs_offset_t filesize;
10406                 skinframe = NULL;
10407                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10408                 if (f)
10409                 {
10410                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10411                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10412                         Mem_Free(f);
10413                 }
10414         }
10415         cache->skinframe = skinframe;
10416 }
10417
10418 texture_t *R_GetCurrentTexture(texture_t *t)
10419 {
10420         int i;
10421         const entity_render_t *ent = rsurface.entity;
10422         dp_model_t *model = ent->model;
10423         q3shaderinfo_layer_tcmod_t *tcmod;
10424
10425         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10426                 return t->currentframe;
10427         t->update_lastrenderframe = r_textureframe;
10428         t->update_lastrenderentity = (void *)ent;
10429
10430         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10431                 t->camera_entity = ent->entitynumber;
10432         else
10433                 t->camera_entity = 0;
10434
10435         // switch to an alternate material if this is a q1bsp animated material
10436         {
10437                 texture_t *texture = t;
10438                 int s = rsurface.ent_skinnum;
10439                 if ((unsigned int)s >= (unsigned int)model->numskins)
10440                         s = 0;
10441                 if (model->skinscenes)
10442                 {
10443                         if (model->skinscenes[s].framecount > 1)
10444                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10445                         else
10446                                 s = model->skinscenes[s].firstframe;
10447                 }
10448                 if (s > 0)
10449                         t = t + s * model->num_surfaces;
10450                 if (t->animated)
10451                 {
10452                         // use an alternate animation if the entity's frame is not 0,
10453                         // and only if the texture has an alternate animation
10454                         if (rsurface.ent_alttextures && t->anim_total[1])
10455                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10456                         else
10457                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10458                 }
10459                 texture->currentframe = t;
10460         }
10461
10462         // update currentskinframe to be a qw skin or animation frame
10463         if (rsurface.ent_qwskin >= 0)
10464         {
10465                 i = rsurface.ent_qwskin;
10466                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10467                 {
10468                         r_qwskincache_size = cl.maxclients;
10469                         if (r_qwskincache)
10470                                 Mem_Free(r_qwskincache);
10471                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10472                 }
10473                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10474                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10475                 t->currentskinframe = r_qwskincache[i].skinframe;
10476                 if (t->currentskinframe == NULL)
10477                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10478         }
10479         else if (t->numskinframes >= 2)
10480                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10481         if (t->backgroundnumskinframes >= 2)
10482                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10483
10484         t->currentmaterialflags = t->basematerialflags;
10485         t->currentalpha = rsurface.colormod[3];
10486         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10487                 t->currentalpha *= r_wateralpha.value;
10488         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10489                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10490         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10491                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10492         if (!(rsurface.ent_flags & RENDER_LIGHT))
10493                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10494         else if (FAKELIGHT_ENABLED)
10495         {
10496                         // no modellight if using fakelight for the map
10497         }
10498         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10499         {
10500                 // pick a model lighting mode
10501                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10502                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10503                 else
10504                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10505         }
10506         if (rsurface.ent_flags & RENDER_ADDITIVE)
10507                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10508         else if (t->currentalpha < 1)
10509                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10510         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10511                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10512         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10513                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10514         if (t->backgroundnumskinframes)
10515                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10516         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10517         {
10518                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10519                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10520         }
10521         else
10522                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10523         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10524                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10525
10526         // there is no tcmod
10527         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10528         {
10529                 t->currenttexmatrix = r_waterscrollmatrix;
10530                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10531         }
10532         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10533         {
10534                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10535                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10536         }
10537
10538         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10539                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10540         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10541                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10542
10543         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10544         if (t->currentskinframe->qpixels)
10545                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10546         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10547         if (!t->basetexture)
10548                 t->basetexture = r_texture_notexture;
10549         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10550         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10551         t->nmaptexture = t->currentskinframe->nmap;
10552         if (!t->nmaptexture)
10553                 t->nmaptexture = r_texture_blanknormalmap;
10554         t->glosstexture = r_texture_black;
10555         t->glowtexture = t->currentskinframe->glow;
10556         t->fogtexture = t->currentskinframe->fog;
10557         t->reflectmasktexture = t->currentskinframe->reflect;
10558         if (t->backgroundnumskinframes)
10559         {
10560                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10561                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10562                 t->backgroundglosstexture = r_texture_black;
10563                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10564                 if (!t->backgroundnmaptexture)
10565                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10566         }
10567         else
10568         {
10569                 t->backgroundbasetexture = r_texture_white;
10570                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10571                 t->backgroundglosstexture = r_texture_black;
10572                 t->backgroundglowtexture = NULL;
10573         }
10574         t->specularpower = r_shadow_glossexponent.value;
10575         // TODO: store reference values for these in the texture?
10576         t->specularscale = 0;
10577         if (r_shadow_gloss.integer > 0)
10578         {
10579                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10580                 {
10581                         if (r_shadow_glossintensity.value > 0)
10582                         {
10583                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10584                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10585                                 t->specularscale = r_shadow_glossintensity.value;
10586                         }
10587                 }
10588                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10589                 {
10590                         t->glosstexture = r_texture_white;
10591                         t->backgroundglosstexture = r_texture_white;
10592                         t->specularscale = r_shadow_gloss2intensity.value;
10593                         t->specularpower = r_shadow_gloss2exponent.value;
10594                 }
10595         }
10596         t->specularscale *= t->specularscalemod;
10597         t->specularpower *= t->specularpowermod;
10598
10599         // lightmaps mode looks bad with dlights using actual texturing, so turn
10600         // off the colormap and glossmap, but leave the normalmap on as it still
10601         // accurately represents the shading involved
10602         if (gl_lightmaps.integer)
10603         {
10604                 t->basetexture = r_texture_grey128;
10605                 t->pantstexture = r_texture_black;
10606                 t->shirttexture = r_texture_black;
10607                 t->nmaptexture = r_texture_blanknormalmap;
10608                 t->glosstexture = r_texture_black;
10609                 t->glowtexture = NULL;
10610                 t->fogtexture = NULL;
10611                 t->reflectmasktexture = NULL;
10612                 t->backgroundbasetexture = NULL;
10613                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10614                 t->backgroundglosstexture = r_texture_black;
10615                 t->backgroundglowtexture = NULL;
10616                 t->specularscale = 0;
10617                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10618         }
10619
10620         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10621         VectorClear(t->dlightcolor);
10622         t->currentnumlayers = 0;
10623         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10624         {
10625                 int blendfunc1, blendfunc2;
10626                 qboolean depthmask;
10627                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10628                 {
10629                         blendfunc1 = GL_SRC_ALPHA;
10630                         blendfunc2 = GL_ONE;
10631                 }
10632                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10633                 {
10634                         blendfunc1 = GL_SRC_ALPHA;
10635                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10636                 }
10637                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10638                 {
10639                         blendfunc1 = t->customblendfunc[0];
10640                         blendfunc2 = t->customblendfunc[1];
10641                 }
10642                 else
10643                 {
10644                         blendfunc1 = GL_ONE;
10645                         blendfunc2 = GL_ZERO;
10646                 }
10647                 // don't colormod evilblend textures
10648                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10649                         VectorSet(t->lightmapcolor, 1, 1, 1);
10650                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10651                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10652                 {
10653                         // fullbright is not affected by r_refdef.lightmapintensity
10654                         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]);
10655                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10656                                 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]);
10657                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10658                                 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]);
10659                 }
10660                 else
10661                 {
10662                         vec3_t ambientcolor;
10663                         float colorscale;
10664                         // set the color tint used for lights affecting this surface
10665                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10666                         colorscale = 2;
10667                         // q3bsp has no lightmap updates, so the lightstylevalue that
10668                         // would normally be baked into the lightmap must be
10669                         // applied to the color
10670                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10671                         if (model->type == mod_brushq3)
10672                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10673                         colorscale *= r_refdef.lightmapintensity;
10674                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10675                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10676                         // basic lit geometry
10677                         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]);
10678                         // add pants/shirt if needed
10679                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10680                                 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]);
10681                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10682                                 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]);
10683                         // now add ambient passes if needed
10684                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10685                         {
10686                                 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]);
10687                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10688                                         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]);
10689                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10690                                         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]);
10691                         }
10692                 }
10693                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10694                         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]);
10695                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10696                 {
10697                         // if this is opaque use alpha blend which will darken the earlier
10698                         // passes cheaply.
10699                         //
10700                         // if this is an alpha blended material, all the earlier passes
10701                         // were darkened by fog already, so we only need to add the fog
10702                         // color ontop through the fog mask texture
10703                         //
10704                         // if this is an additive blended material, all the earlier passes
10705                         // were darkened by fog already, and we should not add fog color
10706                         // (because the background was not darkened, there is no fog color
10707                         // that was lost behind it).
10708                         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]);
10709                 }
10710         }
10711
10712         return t->currentframe;
10713 }
10714
10715 rsurfacestate_t rsurface;
10716
10717 void R_Mesh_ResizeArrays(int newvertices)
10718 {
10719         unsigned char *base;
10720         size_t size;
10721         if (rsurface.array_size >= newvertices)
10722                 return;
10723         if (rsurface.array_base)
10724                 Mem_Free(rsurface.array_base);
10725         rsurface.array_size = (newvertices + 1023) & ~1023;
10726         size = 0;
10727         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10728         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10729         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10730         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10731         size += rsurface.array_size * sizeof(float[3]);
10732         size += rsurface.array_size * sizeof(float[3]);
10733         size += rsurface.array_size * sizeof(float[3]);
10734         size += rsurface.array_size * sizeof(float[3]);
10735         size += rsurface.array_size * sizeof(float[3]);
10736         size += rsurface.array_size * sizeof(float[3]);
10737         size += rsurface.array_size * sizeof(float[3]);
10738         size += rsurface.array_size * sizeof(float[3]);
10739         size += rsurface.array_size * sizeof(float[4]);
10740         size += rsurface.array_size * sizeof(float[2]);
10741         size += rsurface.array_size * sizeof(float[2]);
10742         size += rsurface.array_size * sizeof(float[4]);
10743         size += rsurface.array_size * sizeof(int[3]);
10744         size += rsurface.array_size * sizeof(unsigned short[3]);
10745         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10746         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10747         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10748         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10749         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10750         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10751         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10752         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10753         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10754         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10755         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10756         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10757         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10758         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10759         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10760         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10761         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10762         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10763         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10764 }
10765
10766 void RSurf_ActiveWorldEntity(void)
10767 {
10768         dp_model_t *model = r_refdef.scene.worldmodel;
10769         //if (rsurface.entity == r_refdef.scene.worldentity)
10770         //      return;
10771         rsurface.entity = r_refdef.scene.worldentity;
10772         rsurface.skeleton = NULL;
10773         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10774         rsurface.ent_skinnum = 0;
10775         rsurface.ent_qwskin = -1;
10776         rsurface.ent_shadertime = 0;
10777         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10778         if (rsurface.array_size < model->surfmesh.num_vertices)
10779                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10780         rsurface.matrix = identitymatrix;
10781         rsurface.inversematrix = identitymatrix;
10782         rsurface.matrixscale = 1;
10783         rsurface.inversematrixscale = 1;
10784         R_EntityMatrix(&identitymatrix);
10785         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10786         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10787         rsurface.fograngerecip = r_refdef.fograngerecip;
10788         rsurface.fogheightfade = r_refdef.fogheightfade;
10789         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10790         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10791         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10792         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10793         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10794         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10795         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10796         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10797         rsurface.colormod[3] = 1;
10798         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);
10799         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10800         rsurface.frameblend[0].lerp = 1;
10801         rsurface.ent_alttextures = false;
10802         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10803         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10804         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10805         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10806         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10807         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10808         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10809         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10810         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10811         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10812         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10813         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10814         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10815         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10816         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10817         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10818         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10819         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10820         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10821         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10822         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10823         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10824         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10825         rsurface.modelelement3i = model->surfmesh.data_element3i;
10826         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10827         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10828         rsurface.modelelement3s = model->surfmesh.data_element3s;
10829         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10830         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10831         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10832         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10833         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10834         rsurface.modelsurfaces = model->data_surfaces;
10835         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10836         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10837         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10838         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10839         rsurface.modelgeneratedvertex = false;
10840         rsurface.batchgeneratedvertex = false;
10841         rsurface.batchfirstvertex = 0;
10842         rsurface.batchnumvertices = 0;
10843         rsurface.batchfirsttriangle = 0;
10844         rsurface.batchnumtriangles = 0;
10845         rsurface.batchvertex3f  = NULL;
10846         rsurface.batchvertex3f_vertexbuffer = NULL;
10847         rsurface.batchvertex3f_bufferoffset = 0;
10848         rsurface.batchsvector3f = NULL;
10849         rsurface.batchsvector3f_vertexbuffer = NULL;
10850         rsurface.batchsvector3f_bufferoffset = 0;
10851         rsurface.batchtvector3f = NULL;
10852         rsurface.batchtvector3f_vertexbuffer = NULL;
10853         rsurface.batchtvector3f_bufferoffset = 0;
10854         rsurface.batchnormal3f  = NULL;
10855         rsurface.batchnormal3f_vertexbuffer = NULL;
10856         rsurface.batchnormal3f_bufferoffset = 0;
10857         rsurface.batchlightmapcolor4f = NULL;
10858         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10859         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10860         rsurface.batchtexcoordtexture2f = NULL;
10861         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10862         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10863         rsurface.batchtexcoordlightmap2f = NULL;
10864         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10865         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10866         rsurface.batchvertexmesh = NULL;
10867         rsurface.batchvertexmeshbuffer = NULL;
10868         rsurface.batchvertexposition = NULL;
10869         rsurface.batchvertexpositionbuffer = NULL;
10870         rsurface.batchelement3i = NULL;
10871         rsurface.batchelement3i_indexbuffer = NULL;
10872         rsurface.batchelement3i_bufferoffset = 0;
10873         rsurface.batchelement3s = NULL;
10874         rsurface.batchelement3s_indexbuffer = NULL;
10875         rsurface.batchelement3s_bufferoffset = 0;
10876         rsurface.passcolor4f = NULL;
10877         rsurface.passcolor4f_vertexbuffer = NULL;
10878         rsurface.passcolor4f_bufferoffset = 0;
10879 }
10880
10881 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10882 {
10883         dp_model_t *model = ent->model;
10884         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10885         //      return;
10886         rsurface.entity = (entity_render_t *)ent;
10887         rsurface.skeleton = ent->skeleton;
10888         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10889         rsurface.ent_skinnum = ent->skinnum;
10890         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;
10891         rsurface.ent_shadertime = ent->shadertime;
10892         rsurface.ent_flags = ent->flags;
10893         if (rsurface.array_size < model->surfmesh.num_vertices)
10894                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10895         rsurface.matrix = ent->matrix;
10896         rsurface.inversematrix = ent->inversematrix;
10897         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10898         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10899         R_EntityMatrix(&rsurface.matrix);
10900         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10901         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10902         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10903         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10904         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10905         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10906         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10907         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10908         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10909         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10910         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10911         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10912         rsurface.colormod[3] = ent->alpha;
10913         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10914         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10915         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10916         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10917         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10918         if (ent->model->brush.submodel && !prepass)
10919         {
10920                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10921                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10922         }
10923         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10924         {
10925                 if (ent->animcache_vertex3f && !r_framedata_failed)
10926                 {
10927                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10928                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10929                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10930                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10931                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10932                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10933                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10934                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10935                 }
10936                 else if (wanttangents)
10937                 {
10938                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10939                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10940                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10941                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10942                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10943                         rsurface.modelvertexmesh = NULL;
10944                         rsurface.modelvertexmeshbuffer = NULL;
10945                         rsurface.modelvertexposition = NULL;
10946                         rsurface.modelvertexpositionbuffer = NULL;
10947                 }
10948                 else if (wantnormals)
10949                 {
10950                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10951                         rsurface.modelsvector3f = NULL;
10952                         rsurface.modeltvector3f = NULL;
10953                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10954                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10955                         rsurface.modelvertexmesh = NULL;
10956                         rsurface.modelvertexmeshbuffer = NULL;
10957                         rsurface.modelvertexposition = NULL;
10958                         rsurface.modelvertexpositionbuffer = NULL;
10959                 }
10960                 else
10961                 {
10962                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10963                         rsurface.modelsvector3f = NULL;
10964                         rsurface.modeltvector3f = NULL;
10965                         rsurface.modelnormal3f = NULL;
10966                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10967                         rsurface.modelvertexmesh = NULL;
10968                         rsurface.modelvertexmeshbuffer = NULL;
10969                         rsurface.modelvertexposition = NULL;
10970                         rsurface.modelvertexpositionbuffer = NULL;
10971                 }
10972                 rsurface.modelvertex3f_vertexbuffer = 0;
10973                 rsurface.modelvertex3f_bufferoffset = 0;
10974                 rsurface.modelsvector3f_vertexbuffer = 0;
10975                 rsurface.modelsvector3f_bufferoffset = 0;
10976                 rsurface.modeltvector3f_vertexbuffer = 0;
10977                 rsurface.modeltvector3f_bufferoffset = 0;
10978                 rsurface.modelnormal3f_vertexbuffer = 0;
10979                 rsurface.modelnormal3f_bufferoffset = 0;
10980                 rsurface.modelgeneratedvertex = true;
10981         }
10982         else
10983         {
10984                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10985                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10986                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10987                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10988                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10989                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10990                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10991                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10992                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10993                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10994                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10995                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10996                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10997                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10998                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10999                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11000                 rsurface.modelgeneratedvertex = false;
11001         }
11002         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11003         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11004         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11005         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11006         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11007         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11008         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11009         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11010         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11011         rsurface.modelelement3i = model->surfmesh.data_element3i;
11012         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11013         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11014         rsurface.modelelement3s = model->surfmesh.data_element3s;
11015         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11016         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11017         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11018         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11019         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11020         rsurface.modelsurfaces = model->data_surfaces;
11021         rsurface.batchgeneratedvertex = false;
11022         rsurface.batchfirstvertex = 0;
11023         rsurface.batchnumvertices = 0;
11024         rsurface.batchfirsttriangle = 0;
11025         rsurface.batchnumtriangles = 0;
11026         rsurface.batchvertex3f  = NULL;
11027         rsurface.batchvertex3f_vertexbuffer = NULL;
11028         rsurface.batchvertex3f_bufferoffset = 0;
11029         rsurface.batchsvector3f = NULL;
11030         rsurface.batchsvector3f_vertexbuffer = NULL;
11031         rsurface.batchsvector3f_bufferoffset = 0;
11032         rsurface.batchtvector3f = NULL;
11033         rsurface.batchtvector3f_vertexbuffer = NULL;
11034         rsurface.batchtvector3f_bufferoffset = 0;
11035         rsurface.batchnormal3f  = NULL;
11036         rsurface.batchnormal3f_vertexbuffer = NULL;
11037         rsurface.batchnormal3f_bufferoffset = 0;
11038         rsurface.batchlightmapcolor4f = NULL;
11039         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11040         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11041         rsurface.batchtexcoordtexture2f = NULL;
11042         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11043         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11044         rsurface.batchtexcoordlightmap2f = NULL;
11045         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11046         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11047         rsurface.batchvertexmesh = NULL;
11048         rsurface.batchvertexmeshbuffer = NULL;
11049         rsurface.batchvertexposition = NULL;
11050         rsurface.batchvertexpositionbuffer = NULL;
11051         rsurface.batchelement3i = NULL;
11052         rsurface.batchelement3i_indexbuffer = NULL;
11053         rsurface.batchelement3i_bufferoffset = 0;
11054         rsurface.batchelement3s = NULL;
11055         rsurface.batchelement3s_indexbuffer = NULL;
11056         rsurface.batchelement3s_bufferoffset = 0;
11057         rsurface.passcolor4f = NULL;
11058         rsurface.passcolor4f_vertexbuffer = NULL;
11059         rsurface.passcolor4f_bufferoffset = 0;
11060 }
11061
11062 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)
11063 {
11064         int i;
11065
11066         rsurface.entity = r_refdef.scene.worldentity;
11067         rsurface.skeleton = NULL;
11068         rsurface.ent_skinnum = 0;
11069         rsurface.ent_qwskin = -1;
11070         rsurface.ent_shadertime = shadertime;
11071         rsurface.ent_flags = entflags;
11072         rsurface.modelnumvertices = numvertices;
11073         rsurface.modelnumtriangles = numtriangles;
11074         if (rsurface.array_size < rsurface.modelnumvertices)
11075                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11076         rsurface.matrix = *matrix;
11077         rsurface.inversematrix = *inversematrix;
11078         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11079         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11080         R_EntityMatrix(&rsurface.matrix);
11081         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11082         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11083         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11084         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11085         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11086         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11087         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11088         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11089         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11090         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11091         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11092         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11093         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);
11094         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11095         rsurface.frameblend[0].lerp = 1;
11096         rsurface.ent_alttextures = false;
11097         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11098         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11099         if (wanttangents)
11100         {
11101                 rsurface.modelvertex3f = vertex3f;
11102                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11103                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11104                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11105         }
11106         else if (wantnormals)
11107         {
11108                 rsurface.modelvertex3f = vertex3f;
11109                 rsurface.modelsvector3f = NULL;
11110                 rsurface.modeltvector3f = NULL;
11111                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11112         }
11113         else
11114         {
11115                 rsurface.modelvertex3f = vertex3f;
11116                 rsurface.modelsvector3f = NULL;
11117                 rsurface.modeltvector3f = NULL;
11118                 rsurface.modelnormal3f = NULL;
11119         }
11120         rsurface.modelvertexmesh = NULL;
11121         rsurface.modelvertexmeshbuffer = NULL;
11122         rsurface.modelvertexposition = NULL;
11123         rsurface.modelvertexpositionbuffer = NULL;
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         rsurface.modellightmapcolor4f  = color4f;
11134         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11135         rsurface.modellightmapcolor4f_bufferoffset = 0;
11136         rsurface.modeltexcoordtexture2f  = texcoord2f;
11137         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11138         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11139         rsurface.modeltexcoordlightmap2f  = NULL;
11140         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11141         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11142         rsurface.modelelement3i = element3i;
11143         rsurface.modelelement3i_indexbuffer = NULL;
11144         rsurface.modelelement3i_bufferoffset = 0;
11145         rsurface.modelelement3s = element3s;
11146         rsurface.modelelement3s_indexbuffer = NULL;
11147         rsurface.modelelement3s_bufferoffset = 0;
11148         rsurface.modellightmapoffsets = NULL;
11149         rsurface.modelsurfaces = NULL;
11150         rsurface.batchgeneratedvertex = false;
11151         rsurface.batchfirstvertex = 0;
11152         rsurface.batchnumvertices = 0;
11153         rsurface.batchfirsttriangle = 0;
11154         rsurface.batchnumtriangles = 0;
11155         rsurface.batchvertex3f  = NULL;
11156         rsurface.batchvertex3f_vertexbuffer = NULL;
11157         rsurface.batchvertex3f_bufferoffset = 0;
11158         rsurface.batchsvector3f = NULL;
11159         rsurface.batchsvector3f_vertexbuffer = NULL;
11160         rsurface.batchsvector3f_bufferoffset = 0;
11161         rsurface.batchtvector3f = NULL;
11162         rsurface.batchtvector3f_vertexbuffer = NULL;
11163         rsurface.batchtvector3f_bufferoffset = 0;
11164         rsurface.batchnormal3f  = NULL;
11165         rsurface.batchnormal3f_vertexbuffer = NULL;
11166         rsurface.batchnormal3f_bufferoffset = 0;
11167         rsurface.batchlightmapcolor4f = NULL;
11168         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11169         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11170         rsurface.batchtexcoordtexture2f = NULL;
11171         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11172         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11173         rsurface.batchtexcoordlightmap2f = NULL;
11174         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11175         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11176         rsurface.batchvertexmesh = NULL;
11177         rsurface.batchvertexmeshbuffer = NULL;
11178         rsurface.batchvertexposition = NULL;
11179         rsurface.batchvertexpositionbuffer = NULL;
11180         rsurface.batchelement3i = NULL;
11181         rsurface.batchelement3i_indexbuffer = NULL;
11182         rsurface.batchelement3i_bufferoffset = 0;
11183         rsurface.batchelement3s = NULL;
11184         rsurface.batchelement3s_indexbuffer = NULL;
11185         rsurface.batchelement3s_bufferoffset = 0;
11186         rsurface.passcolor4f = NULL;
11187         rsurface.passcolor4f_vertexbuffer = NULL;
11188         rsurface.passcolor4f_bufferoffset = 0;
11189
11190         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11191         {
11192                 if ((wantnormals || wanttangents) && !normal3f)
11193                 {
11194                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11195                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11196                 }
11197                 if (wanttangents && !svector3f)
11198                 {
11199                         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);
11200                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11201                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11202                 }
11203         }
11204
11205         // now convert arrays into vertexmesh structs
11206         for (i = 0;i < numvertices;i++)
11207         {
11208                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11209                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11210                 if (rsurface.modelsvector3f)
11211                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11212                 if (rsurface.modeltvector3f)
11213                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11214                 if (rsurface.modelnormal3f)
11215                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11216                 if (rsurface.modellightmapcolor4f)
11217                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11218                 if (rsurface.modeltexcoordtexture2f)
11219                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11220                 if (rsurface.modeltexcoordlightmap2f)
11221                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11222         }
11223 }
11224
11225 float RSurf_FogPoint(const float *v)
11226 {
11227         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11228         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11229         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11230         float FogHeightFade = r_refdef.fogheightfade;
11231         float fogfrac;
11232         unsigned int fogmasktableindex;
11233         if (r_refdef.fogplaneviewabove)
11234                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11235         else
11236                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11237         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11238         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11239 }
11240
11241 float RSurf_FogVertex(const float *v)
11242 {
11243         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11244         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11245         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11246         float FogHeightFade = rsurface.fogheightfade;
11247         float fogfrac;
11248         unsigned int fogmasktableindex;
11249         if (r_refdef.fogplaneviewabove)
11250                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11251         else
11252                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11253         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11254         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11255 }
11256
11257 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11258 {
11259         int i;
11260         for (i = 0;i < numelements;i++)
11261                 outelement3i[i] = inelement3i[i] + adjust;
11262 }
11263
11264 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11265 extern cvar_t gl_vbo;
11266 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11267 {
11268         int deformindex;
11269         int firsttriangle;
11270         int numtriangles;
11271         int firstvertex;
11272         int endvertex;
11273         int numvertices;
11274         int surfacefirsttriangle;
11275         int surfacenumtriangles;
11276         int surfacefirstvertex;
11277         int surfaceendvertex;
11278         int surfacenumvertices;
11279         int needsupdate;
11280         int i, j;
11281         qboolean gaps;
11282         qboolean dynamicvertex;
11283         float amplitude;
11284         float animpos;
11285         float scale;
11286         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11287         float waveparms[4];
11288         q3shaderinfo_deform_t *deform;
11289         const msurface_t *surface, *firstsurface;
11290         r_vertexposition_t *vertexposition;
11291         r_vertexmesh_t *vertexmesh;
11292         if (!texturenumsurfaces)
11293                 return;
11294         // find vertex range of this surface batch
11295         gaps = false;
11296         firstsurface = texturesurfacelist[0];
11297         firsttriangle = firstsurface->num_firsttriangle;
11298         numtriangles = 0;
11299         firstvertex = endvertex = firstsurface->num_firstvertex;
11300         for (i = 0;i < texturenumsurfaces;i++)
11301         {
11302                 surface = texturesurfacelist[i];
11303                 if (surface != firstsurface + i)
11304                         gaps = true;
11305                 surfacefirstvertex = surface->num_firstvertex;
11306                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11307                 surfacenumtriangles = surface->num_triangles;
11308                 if (firstvertex > surfacefirstvertex)
11309                         firstvertex = surfacefirstvertex;
11310                 if (endvertex < surfaceendvertex)
11311                         endvertex = surfaceendvertex;
11312                 numtriangles += surfacenumtriangles;
11313         }
11314         if (!numtriangles)
11315                 return;
11316
11317         // we now know the vertex range used, and if there are any gaps in it
11318         rsurface.batchfirstvertex = firstvertex;
11319         rsurface.batchnumvertices = endvertex - firstvertex;
11320         rsurface.batchfirsttriangle = firsttriangle;
11321         rsurface.batchnumtriangles = numtriangles;
11322
11323         // this variable holds flags for which properties have been updated that
11324         // may require regenerating vertexmesh or vertexposition arrays...
11325         needsupdate = 0;
11326
11327         // check if any dynamic vertex processing must occur
11328         dynamicvertex = false;
11329
11330         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11331                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11332         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11333         {
11334                 switch (deform->deform)
11335                 {
11336                 default:
11337                 case Q3DEFORM_PROJECTIONSHADOW:
11338                 case Q3DEFORM_TEXT0:
11339                 case Q3DEFORM_TEXT1:
11340                 case Q3DEFORM_TEXT2:
11341                 case Q3DEFORM_TEXT3:
11342                 case Q3DEFORM_TEXT4:
11343                 case Q3DEFORM_TEXT5:
11344                 case Q3DEFORM_TEXT6:
11345                 case Q3DEFORM_TEXT7:
11346                 case Q3DEFORM_NONE:
11347                         break;
11348                 case Q3DEFORM_AUTOSPRITE:
11349                         dynamicvertex = true;
11350                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11351                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11352                         break;
11353                 case Q3DEFORM_AUTOSPRITE2:
11354                         dynamicvertex = true;
11355                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11356                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11357                         break;
11358                 case Q3DEFORM_NORMAL:
11359                         dynamicvertex = true;
11360                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11361                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11362                         break;
11363                 case Q3DEFORM_WAVE:
11364                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11365                                 break; // if wavefunc is a nop, ignore this transform
11366                         dynamicvertex = true;
11367                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11368                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11369                         break;
11370                 case Q3DEFORM_BULGE:
11371                         dynamicvertex = true;
11372                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11373                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11374                         break;
11375                 case Q3DEFORM_MOVE:
11376                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11377                                 break; // if wavefunc is a nop, ignore this transform
11378                         dynamicvertex = true;
11379                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11380                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11381                         break;
11382                 }
11383         }
11384         switch(rsurface.texture->tcgen.tcgen)
11385         {
11386         default:
11387         case Q3TCGEN_TEXTURE:
11388                 break;
11389         case Q3TCGEN_LIGHTMAP:
11390                 dynamicvertex = true;
11391                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11392                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11393                 break;
11394         case Q3TCGEN_VECTOR:
11395                 dynamicvertex = true;
11396                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11397                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11398                 break;
11399         case Q3TCGEN_ENVIRONMENT:
11400                 dynamicvertex = true;
11401                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11402                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11403                 break;
11404         }
11405         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11406         {
11407                 dynamicvertex = true;
11408                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11409                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11410         }
11411
11412         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11413         {
11414                 dynamicvertex = true;
11415                 batchneed |= BATCHNEED_NOGAPS;
11416                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11417         }
11418
11419         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11420         {
11421                 dynamicvertex = true;
11422                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11423                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11424         }
11425
11426         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11427         {
11428                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11429                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11430                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11431                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11432                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11433                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11434                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11435         }
11436
11437         // when the model data has no vertex buffer (dynamic mesh), we need to
11438         // eliminate gaps
11439         if (!rsurface.modelvertexmeshbuffer)
11440                 batchneed |= BATCHNEED_NOGAPS;
11441
11442         // if needsupdate, we have to do a dynamic vertex batch for sure
11443         if (needsupdate & batchneed)
11444                 dynamicvertex = true;
11445
11446         // see if we need to build vertexmesh from arrays
11447         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11448                 dynamicvertex = true;
11449
11450         // see if we need to build vertexposition from arrays
11451         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11452                 dynamicvertex = true;
11453
11454         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11455         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11456                 dynamicvertex = true;
11457
11458         // if there is a chance of animated vertex colors, it's a dynamic batch
11459         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11460                 dynamicvertex = true;
11461
11462         rsurface.batchvertex3f = rsurface.modelvertex3f;
11463         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11464         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11465         rsurface.batchsvector3f = rsurface.modelsvector3f;
11466         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11467         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11468         rsurface.batchtvector3f = rsurface.modeltvector3f;
11469         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11470         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11471         rsurface.batchnormal3f = rsurface.modelnormal3f;
11472         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11473         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11474         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11475         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11476         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11477         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11478         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11479         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11480         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11481         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11482         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11483         rsurface.batchvertexposition = rsurface.modelvertexposition;
11484         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11485         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11486         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11487         rsurface.batchelement3i = rsurface.modelelement3i;
11488         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11489         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11490         rsurface.batchelement3s = rsurface.modelelement3s;
11491         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11492         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11493
11494         // if any dynamic vertex processing has to occur in software, we copy the
11495         // entire surface list together before processing to rebase the vertices
11496         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11497         //
11498         // if any gaps exist and we do not have a static vertex buffer, we have to
11499         // copy the surface list together to avoid wasting upload bandwidth on the
11500         // vertices in the gaps.
11501         //
11502         // if gaps exist and we have a static vertex buffer, we still have to
11503         // combine the index buffer ranges into one dynamic index buffer.
11504         //
11505         // in all cases we end up with data that can be drawn in one call.
11506
11507         if (!dynamicvertex)
11508         {
11509                 // static vertex data, just set pointers...
11510                 rsurface.batchgeneratedvertex = false;
11511                 // if there are gaps, we want to build a combined index buffer,
11512                 // otherwise use the original static buffer with an appropriate offset
11513                 if (gaps)
11514                 {
11515                         firsttriangle = 0;
11516                         numtriangles = 0;
11517                         for (i = 0;i < texturenumsurfaces;i++)
11518                         {
11519                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11520                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11521                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11522                                 numtriangles += surfacenumtriangles;
11523                         }
11524                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11525                         rsurface.batchelement3i_indexbuffer = NULL;
11526                         rsurface.batchelement3i_bufferoffset = 0;
11527                         rsurface.batchelement3s = NULL;
11528                         rsurface.batchelement3s_indexbuffer = NULL;
11529                         rsurface.batchelement3s_bufferoffset = 0;
11530                         if (endvertex <= 65536)
11531                         {
11532                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11533                                 for (i = 0;i < numtriangles*3;i++)
11534                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11535                         }
11536                         rsurface.batchfirsttriangle = firsttriangle;
11537                         rsurface.batchnumtriangles = numtriangles;
11538                 }
11539                 return;
11540         }
11541
11542         // something needs software processing, do it for real...
11543         // we only directly handle interleaved array data in this case...
11544         rsurface.batchgeneratedvertex = true;
11545
11546         // now copy the vertex data into a combined array and make an index array
11547         // (this is what Quake3 does all the time)
11548         //if (gaps || rsurface.batchfirstvertex)
11549         {
11550                 rsurface.batchvertexposition = NULL;
11551                 rsurface.batchvertexpositionbuffer = NULL;
11552                 rsurface.batchvertexmesh = NULL;
11553                 rsurface.batchvertexmeshbuffer = NULL;
11554                 rsurface.batchvertex3f = NULL;
11555                 rsurface.batchvertex3f_vertexbuffer = NULL;
11556                 rsurface.batchvertex3f_bufferoffset = 0;
11557                 rsurface.batchsvector3f = NULL;
11558                 rsurface.batchsvector3f_vertexbuffer = NULL;
11559                 rsurface.batchsvector3f_bufferoffset = 0;
11560                 rsurface.batchtvector3f = NULL;
11561                 rsurface.batchtvector3f_vertexbuffer = NULL;
11562                 rsurface.batchtvector3f_bufferoffset = 0;
11563                 rsurface.batchnormal3f = NULL;
11564                 rsurface.batchnormal3f_vertexbuffer = NULL;
11565                 rsurface.batchnormal3f_bufferoffset = 0;
11566                 rsurface.batchlightmapcolor4f = NULL;
11567                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11568                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11569                 rsurface.batchtexcoordtexture2f = NULL;
11570                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11571                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11572                 rsurface.batchtexcoordlightmap2f = NULL;
11573                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11574                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11575                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11576                 rsurface.batchelement3i_indexbuffer = NULL;
11577                 rsurface.batchelement3i_bufferoffset = 0;
11578                 rsurface.batchelement3s = NULL;
11579                 rsurface.batchelement3s_indexbuffer = NULL;
11580                 rsurface.batchelement3s_bufferoffset = 0;
11581                 // we'll only be setting up certain arrays as needed
11582                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11583                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11584                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11585                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11586                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11587                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11588                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11589                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11590                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11591                 {
11592                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11593                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11594                 }
11595                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11596                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11597                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11598                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11599                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11600                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11601                 numvertices = 0;
11602                 numtriangles = 0;
11603                 for (i = 0;i < texturenumsurfaces;i++)
11604                 {
11605                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11606                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11607                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11608                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11609                         // copy only the data requested
11610                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11611                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11612                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11613                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11614                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11615                         {
11616                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11617                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11618                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11619                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11620                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11621                                 {
11622                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11623                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11624                                 }
11625                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11626                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11627                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11628                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11629                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11630                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11631                         }
11632                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11633                         numvertices += surfacenumvertices;
11634                         numtriangles += surfacenumtriangles;
11635                 }
11636
11637                 // generate a 16bit index array as well if possible
11638                 // (in general, dynamic batches fit)
11639                 if (numvertices <= 65536)
11640                 {
11641                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11642                         for (i = 0;i < numtriangles*3;i++)
11643                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11644                 }
11645
11646                 // since we've copied everything, the batch now starts at 0
11647                 rsurface.batchfirstvertex = 0;
11648                 rsurface.batchnumvertices = numvertices;
11649                 rsurface.batchfirsttriangle = 0;
11650                 rsurface.batchnumtriangles = numtriangles;
11651         }
11652
11653         // q1bsp surfaces rendered in vertex color mode have to have colors
11654         // calculated based on lightstyles
11655         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11656         {
11657                 // generate color arrays for the surfaces in this list
11658                 int c[4];
11659                 int scale;
11660                 int size3;
11661                 const int *offsets;
11662                 const unsigned char *lm;
11663                 numvertices = 0;
11664                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11665                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11666                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11667                 for (i = 0;i < texturenumsurfaces;i++)
11668                 {
11669                         surface = texturesurfacelist[i];
11670                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11671                         surfacenumvertices = surface->num_vertices;
11672                         if (surface->lightmapinfo->samples)
11673                         {
11674                                 for (j = 0;j < surfacenumvertices;j++)
11675                                 {
11676                                         lm = surface->lightmapinfo->samples + offsets[j];
11677                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11678                                         VectorScale(lm, scale, c);
11679                                         if (surface->lightmapinfo->styles[1] != 255)
11680                                         {
11681                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11682                                                 lm += size3;
11683                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11684                                                 VectorMA(c, scale, lm, c);
11685                                                 if (surface->lightmapinfo->styles[2] != 255)
11686                                                 {
11687                                                         lm += size3;
11688                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11689                                                         VectorMA(c, scale, lm, c);
11690                                                         if (surface->lightmapinfo->styles[3] != 255)
11691                                                         {
11692                                                                 lm += size3;
11693                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11694                                                                 VectorMA(c, scale, lm, c);
11695                                                         }
11696                                                 }
11697                                         }
11698                                         c[0] >>= 15;
11699                                         c[1] >>= 15;
11700                                         c[2] >>= 15;
11701                                         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);
11702                                         numvertices++;
11703                                 }
11704                         }
11705                         else
11706                         {
11707                                 for (j = 0;j < surfacenumvertices;j++)
11708                                 {
11709                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11710                                         numvertices++;
11711                                 }
11712                         }
11713                 }
11714         }
11715
11716         // if vertices are deformed (sprite flares and things in maps, possibly
11717         // water waves, bulges and other deformations), modify the copied vertices
11718         // in place
11719         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11720         {
11721                 switch (deform->deform)
11722                 {
11723                 default:
11724                 case Q3DEFORM_PROJECTIONSHADOW:
11725                 case Q3DEFORM_TEXT0:
11726                 case Q3DEFORM_TEXT1:
11727                 case Q3DEFORM_TEXT2:
11728                 case Q3DEFORM_TEXT3:
11729                 case Q3DEFORM_TEXT4:
11730                 case Q3DEFORM_TEXT5:
11731                 case Q3DEFORM_TEXT6:
11732                 case Q3DEFORM_TEXT7:
11733                 case Q3DEFORM_NONE:
11734                         break;
11735                 case Q3DEFORM_AUTOSPRITE:
11736                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11737                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11738                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11739                         VectorNormalize(newforward);
11740                         VectorNormalize(newright);
11741                         VectorNormalize(newup);
11742                         // a single autosprite surface can contain multiple sprites...
11743                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11744                         {
11745                                 VectorClear(center);
11746                                 for (i = 0;i < 4;i++)
11747                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11748                                 VectorScale(center, 0.25f, center);
11749                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11750                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11751                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11752                                 for (i = 0;i < 4;i++)
11753                                 {
11754                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11755                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11756                                 }
11757                         }
11758                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11759                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11760                         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, true);
11761                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11762                         rsurface.batchvertex3f_vertexbuffer = NULL;
11763                         rsurface.batchvertex3f_bufferoffset = 0;
11764                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11765                         rsurface.batchsvector3f_vertexbuffer = NULL;
11766                         rsurface.batchsvector3f_bufferoffset = 0;
11767                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11768                         rsurface.batchtvector3f_vertexbuffer = NULL;
11769                         rsurface.batchtvector3f_bufferoffset = 0;
11770                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11771                         rsurface.batchnormal3f_vertexbuffer = NULL;
11772                         rsurface.batchnormal3f_bufferoffset = 0;
11773                         break;
11774                 case Q3DEFORM_AUTOSPRITE2:
11775                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11776                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11777                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11778                         VectorNormalize(newforward);
11779                         VectorNormalize(newright);
11780                         VectorNormalize(newup);
11781                         {
11782                                 const float *v1, *v2;
11783                                 vec3_t start, end;
11784                                 float f, l;
11785                                 struct
11786                                 {
11787                                         float length2;
11788                                         const float *v1;
11789                                         const float *v2;
11790                                 }
11791                                 shortest[2];
11792                                 memset(shortest, 0, sizeof(shortest));
11793                                 // a single autosprite surface can contain multiple sprites...
11794                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11795                                 {
11796                                         VectorClear(center);
11797                                         for (i = 0;i < 4;i++)
11798                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11799                                         VectorScale(center, 0.25f, center);
11800                                         // find the two shortest edges, then use them to define the
11801                                         // axis vectors for rotating around the central axis
11802                                         for (i = 0;i < 6;i++)
11803                                         {
11804                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11805                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11806                                                 l = VectorDistance2(v1, v2);
11807                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11808                                                 if (v1[2] != v2[2])
11809                                                         l += (1.0f / 1024.0f);
11810                                                 if (shortest[0].length2 > l || i == 0)
11811                                                 {
11812                                                         shortest[1] = shortest[0];
11813                                                         shortest[0].length2 = l;
11814                                                         shortest[0].v1 = v1;
11815                                                         shortest[0].v2 = v2;
11816                                                 }
11817                                                 else if (shortest[1].length2 > l || i == 1)
11818                                                 {
11819                                                         shortest[1].length2 = l;
11820                                                         shortest[1].v1 = v1;
11821                                                         shortest[1].v2 = v2;
11822                                                 }
11823                                         }
11824                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11825                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11826                                         // this calculates the right vector from the shortest edge
11827                                         // and the up vector from the edge midpoints
11828                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11829                                         VectorNormalize(right);
11830                                         VectorSubtract(end, start, up);
11831                                         VectorNormalize(up);
11832                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11833                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11834                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11835                                         VectorNegate(forward, forward);
11836                                         VectorReflect(forward, 0, up, forward);
11837                                         VectorNormalize(forward);
11838                                         CrossProduct(up, forward, newright);
11839                                         VectorNormalize(newright);
11840                                         // rotate the quad around the up axis vector, this is made
11841                                         // especially easy by the fact we know the quad is flat,
11842                                         // so we only have to subtract the center position and
11843                                         // measure distance along the right vector, and then
11844                                         // multiply that by the newright vector and add back the
11845                                         // center position
11846                                         // we also need to subtract the old position to undo the
11847                                         // displacement from the center, which we do with a
11848                                         // DotProduct, the subtraction/addition of center is also
11849                                         // optimized into DotProducts here
11850                                         l = DotProduct(right, center);
11851                                         for (i = 0;i < 4;i++)
11852                                         {
11853                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11854                                                 f = DotProduct(right, v1) - l;
11855                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11856                                         }
11857                                 }
11858                         }
11859                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11860                         rsurface.batchvertex3f_vertexbuffer = NULL;
11861                         rsurface.batchvertex3f_bufferoffset = 0;
11862                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11863                         {
11864                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11865                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11866                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11867                                 rsurface.batchnormal3f_bufferoffset = 0;
11868                         }
11869                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11870                         {
11871                                 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, true);
11872                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11873                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11874                                 rsurface.batchsvector3f_bufferoffset = 0;
11875                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11876                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11877                                 rsurface.batchtvector3f_bufferoffset = 0;
11878                         }
11879                         break;
11880                 case Q3DEFORM_NORMAL:
11881                         // deform the normals to make reflections wavey
11882                         for (j = 0;j < rsurface.batchnumvertices;j++)
11883                         {
11884                                 float vertex[3];
11885                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11886                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11887                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11888                                 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]);
11889                                 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]);
11890                                 VectorNormalize(normal);
11891                         }
11892                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11893                         rsurface.batchnormal3f_vertexbuffer = NULL;
11894                         rsurface.batchnormal3f_bufferoffset = 0;
11895                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11896                         {
11897                                 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, true);
11898                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11899                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11900                                 rsurface.batchsvector3f_bufferoffset = 0;
11901                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11902                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11903                                 rsurface.batchtvector3f_bufferoffset = 0;
11904                         }
11905                         break;
11906                 case Q3DEFORM_WAVE:
11907                         // deform vertex array to make wavey water and flags and such
11908                         waveparms[0] = deform->waveparms[0];
11909                         waveparms[1] = deform->waveparms[1];
11910                         waveparms[2] = deform->waveparms[2];
11911                         waveparms[3] = deform->waveparms[3];
11912                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11913                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11914                         // this is how a divisor of vertex influence on deformation
11915                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11916                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11917                         for (j = 0;j < rsurface.batchnumvertices;j++)
11918                         {
11919                                 // if the wavefunc depends on time, evaluate it per-vertex
11920                                 if (waveparms[3])
11921                                 {
11922                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11923                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11924                                 }
11925                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11926                         }
11927                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11928                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11929                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11930                         rsurface.batchvertex3f_vertexbuffer = NULL;
11931                         rsurface.batchvertex3f_bufferoffset = 0;
11932                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11933                         rsurface.batchnormal3f_vertexbuffer = NULL;
11934                         rsurface.batchnormal3f_bufferoffset = 0;
11935                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11936                         {
11937                                 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, true);
11938                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11939                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11940                                 rsurface.batchsvector3f_bufferoffset = 0;
11941                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11942                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11943                                 rsurface.batchtvector3f_bufferoffset = 0;
11944                         }
11945                         break;
11946                 case Q3DEFORM_BULGE:
11947                         // deform vertex array to make the surface have moving bulges
11948                         for (j = 0;j < rsurface.batchnumvertices;j++)
11949                         {
11950                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11951                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11952                         }
11953                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11954                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11955                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11956                         rsurface.batchvertex3f_vertexbuffer = NULL;
11957                         rsurface.batchvertex3f_bufferoffset = 0;
11958                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11959                         rsurface.batchnormal3f_vertexbuffer = NULL;
11960                         rsurface.batchnormal3f_bufferoffset = 0;
11961                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11962                         {
11963                                 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, true);
11964                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11965                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11966                                 rsurface.batchsvector3f_bufferoffset = 0;
11967                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11968                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11969                                 rsurface.batchtvector3f_bufferoffset = 0;
11970                         }
11971                         break;
11972                 case Q3DEFORM_MOVE:
11973                         // deform vertex array
11974                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11975                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11976                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11977                         VectorScale(deform->parms, scale, waveparms);
11978                         for (j = 0;j < rsurface.batchnumvertices;j++)
11979                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11980                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11981                         rsurface.batchvertex3f_vertexbuffer = NULL;
11982                         rsurface.batchvertex3f_bufferoffset = 0;
11983                         break;
11984                 }
11985         }
11986
11987         // generate texcoords based on the chosen texcoord source
11988         switch(rsurface.texture->tcgen.tcgen)
11989         {
11990         default:
11991         case Q3TCGEN_TEXTURE:
11992                 break;
11993         case Q3TCGEN_LIGHTMAP:
11994                 if (rsurface.batchtexcoordlightmap2f)
11995                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11996                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11997                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11998                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11999                 break;
12000         case Q3TCGEN_VECTOR:
12001                 for (j = 0;j < rsurface.batchnumvertices;j++)
12002                 {
12003                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12004                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12005                 }
12006                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12007                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12008                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12009                 break;
12010         case Q3TCGEN_ENVIRONMENT:
12011                 // make environment reflections using a spheremap
12012                 for (j = 0;j < rsurface.batchnumvertices;j++)
12013                 {
12014                         // identical to Q3A's method, but executed in worldspace so
12015                         // carried models can be shiny too
12016
12017                         float viewer[3], d, reflected[3], worldreflected[3];
12018
12019                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12020                         // VectorNormalize(viewer);
12021
12022                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12023
12024                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12025                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12026                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12027                         // note: this is proportinal to viewer, so we can normalize later
12028
12029                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12030                         VectorNormalize(worldreflected);
12031
12032                         // note: this sphere map only uses world x and z!
12033                         // so positive and negative y will LOOK THE SAME.
12034                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12035                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12036                 }
12037                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12038                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12039                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12040                 break;
12041         }
12042         // the only tcmod that needs software vertex processing is turbulent, so
12043         // check for it here and apply the changes if needed
12044         // and we only support that as the first one
12045         // (handling a mixture of turbulent and other tcmods would be problematic
12046         //  without punting it entirely to a software path)
12047         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12048         {
12049                 amplitude = rsurface.texture->tcmods[0].parms[1];
12050                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12051                 for (j = 0;j < rsurface.batchnumvertices;j++)
12052                 {
12053                         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);
12054                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12055                 }
12056                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12057                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12058                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12059         }
12060
12061         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12062         {
12063                 // convert the modified arrays to vertex structs
12064                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12065                 rsurface.batchvertexmeshbuffer = NULL;
12066                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12067                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12068                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12069                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12070                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12071                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12072                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12073                 {
12074                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12075                         {
12076                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12077                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12078                         }
12079                 }
12080                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12081                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12082                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12083                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12084                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12085                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12086                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12087                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12088                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12089         }
12090
12091         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12092         {
12093                 // convert the modified arrays to vertex structs
12094                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12095                 rsurface.batchvertexpositionbuffer = NULL;
12096                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12097                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12098                 else
12099                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12100                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12101         }
12102 }
12103
12104 void RSurf_DrawBatch(void)
12105 {
12106         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);
12107 }
12108
12109 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12110 {
12111         // pick the closest matching water plane
12112         int planeindex, vertexindex, bestplaneindex = -1;
12113         float d, bestd;
12114         vec3_t vert;
12115         const float *v;
12116         r_waterstate_waterplane_t *p;
12117         bestd = 0;
12118         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12119         {
12120                 if(p->camera_entity != rsurface.texture->camera_entity)
12121                         continue;
12122                 d = 0;
12123                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12124                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12125                 {
12126                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12127                         d += fabs(PlaneDiff(vert, &p->plane));
12128                 }
12129                 if (bestd > d || bestplaneindex < 0)
12130                 {
12131                         bestd = d;
12132                         bestplaneindex = planeindex;
12133                 }
12134         }
12135         return bestplaneindex;
12136 }
12137
12138 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12139 {
12140         int i;
12141         for (i = 0;i < rsurface.batchnumvertices;i++)
12142                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12143         rsurface.passcolor4f = rsurface.array_passcolor4f;
12144         rsurface.passcolor4f_vertexbuffer = 0;
12145         rsurface.passcolor4f_bufferoffset = 0;
12146 }
12147
12148 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12149 {
12150         int i;
12151         float f;
12152         const float *v;
12153         const float *c;
12154         float *c2;
12155         if (rsurface.passcolor4f)
12156         {
12157                 // generate color arrays
12158                 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)
12159                 {
12160                         f = RSurf_FogVertex(v);
12161                         c2[0] = c[0] * f;
12162                         c2[1] = c[1] * f;
12163                         c2[2] = c[2] * f;
12164                         c2[3] = c[3];
12165                 }
12166         }
12167         else
12168         {
12169                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12170                 {
12171                         f = RSurf_FogVertex(v);
12172                         c2[0] = f;
12173                         c2[1] = f;
12174                         c2[2] = f;
12175                         c2[3] = 1;
12176                 }
12177         }
12178         rsurface.passcolor4f = rsurface.array_passcolor4f;
12179         rsurface.passcolor4f_vertexbuffer = 0;
12180         rsurface.passcolor4f_bufferoffset = 0;
12181 }
12182
12183 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12184 {
12185         int i;
12186         float f;
12187         const float *v;
12188         const float *c;
12189         float *c2;
12190         if (!rsurface.passcolor4f)
12191                 return;
12192         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)
12193         {
12194                 f = RSurf_FogVertex(v);
12195                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12196                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12197                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12198                 c2[3] = c[3];
12199         }
12200         rsurface.passcolor4f = rsurface.array_passcolor4f;
12201         rsurface.passcolor4f_vertexbuffer = 0;
12202         rsurface.passcolor4f_bufferoffset = 0;
12203 }
12204
12205 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12206 {
12207         int i;
12208         const float *c;
12209         float *c2;
12210         if (!rsurface.passcolor4f)
12211                 return;
12212         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12213         {
12214                 c2[0] = c[0] * r;
12215                 c2[1] = c[1] * g;
12216                 c2[2] = c[2] * b;
12217                 c2[3] = c[3] * a;
12218         }
12219         rsurface.passcolor4f = rsurface.array_passcolor4f;
12220         rsurface.passcolor4f_vertexbuffer = 0;
12221         rsurface.passcolor4f_bufferoffset = 0;
12222 }
12223
12224 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12225 {
12226         int i;
12227         const float *c;
12228         float *c2;
12229         if (!rsurface.passcolor4f)
12230                 return;
12231         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12232         {
12233                 c2[0] = c[0] + r_refdef.scene.ambient;
12234                 c2[1] = c[1] + r_refdef.scene.ambient;
12235                 c2[2] = c[2] + r_refdef.scene.ambient;
12236                 c2[3] = c[3];
12237         }
12238         rsurface.passcolor4f = rsurface.array_passcolor4f;
12239         rsurface.passcolor4f_vertexbuffer = 0;
12240         rsurface.passcolor4f_bufferoffset = 0;
12241 }
12242
12243 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12244 {
12245         // TODO: optimize
12246         rsurface.passcolor4f = NULL;
12247         rsurface.passcolor4f_vertexbuffer = 0;
12248         rsurface.passcolor4f_bufferoffset = 0;
12249         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12250         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12251         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12252         GL_Color(r, g, b, a);
12253         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12254         RSurf_DrawBatch();
12255 }
12256
12257 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12258 {
12259         // TODO: optimize applyfog && applycolor case
12260         // just apply fog if necessary, and tint the fog color array if necessary
12261         rsurface.passcolor4f = NULL;
12262         rsurface.passcolor4f_vertexbuffer = 0;
12263         rsurface.passcolor4f_bufferoffset = 0;
12264         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12265         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12266         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12267         GL_Color(r, g, b, a);
12268         RSurf_DrawBatch();
12269 }
12270
12271 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12272 {
12273         // TODO: optimize
12274         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12275         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12276         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12277         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12278         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12279         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12280         GL_Color(r, g, b, a);
12281         RSurf_DrawBatch();
12282 }
12283
12284 static void RSurf_DrawBatch_GL11_ClampColor(void)
12285 {
12286         int i;
12287         const float *c1;
12288         float *c2;
12289         if (!rsurface.passcolor4f)
12290                 return;
12291         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12292         {
12293                 c2[0] = bound(0.0f, c1[0], 1.0f);
12294                 c2[1] = bound(0.0f, c1[1], 1.0f);
12295                 c2[2] = bound(0.0f, c1[2], 1.0f);
12296                 c2[3] = bound(0.0f, c1[3], 1.0f);
12297         }
12298 }
12299
12300 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12301 {
12302         int i;
12303         float f;
12304         const float *v;
12305         const float *n;
12306         float *c;
12307         //vec3_t eyedir;
12308
12309         // fake shading
12310         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)
12311         {
12312                 f = -DotProduct(r_refdef.view.forward, n);
12313                 f = max(0, f);
12314                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12315                 f *= r_refdef.lightmapintensity;
12316                 Vector4Set(c, f, f, f, 1);
12317         }
12318
12319         rsurface.passcolor4f = rsurface.array_passcolor4f;
12320         rsurface.passcolor4f_vertexbuffer = 0;
12321         rsurface.passcolor4f_bufferoffset = 0;
12322 }
12323
12324 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12325 {
12326         RSurf_DrawBatch_GL11_ApplyFakeLight();
12327         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12328         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12329         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12330         GL_Color(r, g, b, a);
12331         RSurf_DrawBatch();
12332 }
12333
12334 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12335 {
12336         int i;
12337         float f;
12338         float alpha;
12339         const float *v;
12340         const float *n;
12341         float *c;
12342         vec3_t ambientcolor;
12343         vec3_t diffusecolor;
12344         vec3_t lightdir;
12345         // TODO: optimize
12346         // model lighting
12347         VectorCopy(rsurface.modellight_lightdir, lightdir);
12348         f = 0.5f * r_refdef.lightmapintensity;
12349         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12350         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12351         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12352         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12353         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12354         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12355         alpha = *a;
12356         if (VectorLength2(diffusecolor) > 0)
12357         {
12358                 // q3-style directional shading
12359                 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)
12360                 {
12361                         if ((f = DotProduct(n, lightdir)) > 0)
12362                                 VectorMA(ambientcolor, f, diffusecolor, c);
12363                         else
12364                                 VectorCopy(ambientcolor, c);
12365                         c[3] = alpha;
12366                 }
12367                 *r = 1;
12368                 *g = 1;
12369                 *b = 1;
12370                 *a = 1;
12371                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12372                 rsurface.passcolor4f_vertexbuffer = 0;
12373                 rsurface.passcolor4f_bufferoffset = 0;
12374                 *applycolor = false;
12375         }
12376         else
12377         {
12378                 *r = ambientcolor[0];
12379                 *g = ambientcolor[1];
12380                 *b = ambientcolor[2];
12381                 rsurface.passcolor4f = NULL;
12382                 rsurface.passcolor4f_vertexbuffer = 0;
12383                 rsurface.passcolor4f_bufferoffset = 0;
12384         }
12385 }
12386
12387 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12388 {
12389         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12390         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12391         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12392         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12393         GL_Color(r, g, b, a);
12394         RSurf_DrawBatch();
12395 }
12396
12397 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12398 {
12399         int i;
12400         float f;
12401         const float *v;
12402         float *c;
12403         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12404         {
12405                 f = 1 - RSurf_FogVertex(v);
12406                 c[0] = r;
12407                 c[1] = g;
12408                 c[2] = b;
12409                 c[3] = f * a;
12410         }
12411 }
12412
12413 void RSurf_SetupDepthAndCulling(void)
12414 {
12415         // submodels are biased to avoid z-fighting with world surfaces that they
12416         // may be exactly overlapping (avoids z-fighting artifacts on certain
12417         // doors and things in Quake maps)
12418         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12419         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12420         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12421         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12422 }
12423
12424 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12425 {
12426         // transparent sky would be ridiculous
12427         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12428                 return;
12429         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12430         skyrenderlater = true;
12431         RSurf_SetupDepthAndCulling();
12432         GL_DepthMask(true);
12433         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12434         // skymasking on them, and Quake3 never did sky masking (unlike
12435         // software Quake and software Quake2), so disable the sky masking
12436         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12437         // and skymasking also looks very bad when noclipping outside the
12438         // level, so don't use it then either.
12439         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12440         {
12441                 R_Mesh_ResetTextureState();
12442                 if (skyrendermasked)
12443                 {
12444                         R_SetupShader_DepthOrShadow();
12445                         // depth-only (masking)
12446                         GL_ColorMask(0,0,0,0);
12447                         // just to make sure that braindead drivers don't draw
12448                         // anything despite that colormask...
12449                         GL_BlendFunc(GL_ZERO, GL_ONE);
12450                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12451                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12452                 }
12453                 else
12454                 {
12455                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12456                         // fog sky
12457                         GL_BlendFunc(GL_ONE, GL_ZERO);
12458                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12459                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12460                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12461                 }
12462                 RSurf_DrawBatch();
12463                 if (skyrendermasked)
12464                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12465         }
12466         R_Mesh_ResetTextureState();
12467         GL_Color(1, 1, 1, 1);
12468 }
12469
12470 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12471 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12472 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12473 {
12474         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12475                 return;
12476         if (prepass)
12477         {
12478                 // render screenspace normalmap to texture
12479                 GL_DepthMask(true);
12480                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12481                 RSurf_DrawBatch();
12482                 return;
12483         }
12484
12485         // bind lightmap texture
12486
12487         // water/refraction/reflection/camera surfaces have to be handled specially
12488         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12489         {
12490                 int start, end, startplaneindex;
12491                 for (start = 0;start < texturenumsurfaces;start = end)
12492                 {
12493                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12494                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12495                                 ;
12496                         // now that we have a batch using the same planeindex, render it
12497                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12498                         {
12499                                 // render water or distortion background
12500                                 GL_DepthMask(true);
12501                                 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));
12502                                 RSurf_DrawBatch();
12503                                 // blend surface on top
12504                                 GL_DepthMask(false);
12505                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12506                                 RSurf_DrawBatch();
12507                         }
12508                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12509                         {
12510                                 // render surface with reflection texture as input
12511                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12512                                 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));
12513                                 RSurf_DrawBatch();
12514                         }
12515                 }
12516                 return;
12517         }
12518
12519         // render surface batch normally
12520         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12521         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12522         RSurf_DrawBatch();
12523 }
12524
12525 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12526 {
12527         // OpenGL 1.3 path - anything not completely ancient
12528         qboolean applycolor;
12529         qboolean applyfog;
12530         int layerindex;
12531         const texturelayer_t *layer;
12532         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);
12533         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12534
12535         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12536         {
12537                 vec4_t layercolor;
12538                 int layertexrgbscale;
12539                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12540                 {
12541                         if (layerindex == 0)
12542                                 GL_AlphaTest(true);
12543                         else
12544                         {
12545                                 GL_AlphaTest(false);
12546                                 GL_DepthFunc(GL_EQUAL);
12547                         }
12548                 }
12549                 GL_DepthMask(layer->depthmask && writedepth);
12550                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12551                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12552                 {
12553                         layertexrgbscale = 4;
12554                         VectorScale(layer->color, 0.25f, layercolor);
12555                 }
12556                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12557                 {
12558                         layertexrgbscale = 2;
12559                         VectorScale(layer->color, 0.5f, layercolor);
12560                 }
12561                 else
12562                 {
12563                         layertexrgbscale = 1;
12564                         VectorScale(layer->color, 1.0f, layercolor);
12565                 }
12566                 layercolor[3] = layer->color[3];
12567                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12568                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12569                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12570                 switch (layer->type)
12571                 {
12572                 case TEXTURELAYERTYPE_LITTEXTURE:
12573                         // single-pass lightmapped texture with 2x rgbscale
12574                         R_Mesh_TexBind(0, r_texture_white);
12575                         R_Mesh_TexMatrix(0, NULL);
12576                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12577                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12578                         R_Mesh_TexBind(1, layer->texture);
12579                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12580                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12581                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12582                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12583                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12584                         else if (FAKELIGHT_ENABLED)
12585                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12586                         else if (rsurface.uselightmaptexture)
12587                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12588                         else
12589                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12590                         break;
12591                 case TEXTURELAYERTYPE_TEXTURE:
12592                         // singletexture unlit texture with transparency support
12593                         R_Mesh_TexBind(0, layer->texture);
12594                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12595                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12596                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12597                         R_Mesh_TexBind(1, 0);
12598                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12599                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12600                         break;
12601                 case TEXTURELAYERTYPE_FOG:
12602                         // singletexture fogging
12603                         if (layer->texture)
12604                         {
12605                                 R_Mesh_TexBind(0, layer->texture);
12606                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12607                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12608                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12609                         }
12610                         else
12611                         {
12612                                 R_Mesh_TexBind(0, 0);
12613                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12614                         }
12615                         R_Mesh_TexBind(1, 0);
12616                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12617                         // generate a color array for the fog pass
12618                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12619                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12620                         RSurf_DrawBatch();
12621                         break;
12622                 default:
12623                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12624                 }
12625         }
12626         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12627         {
12628                 GL_DepthFunc(GL_LEQUAL);
12629                 GL_AlphaTest(false);
12630         }
12631 }
12632
12633 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12634 {
12635         // OpenGL 1.1 - crusty old voodoo path
12636         qboolean applyfog;
12637         int layerindex;
12638         const texturelayer_t *layer;
12639         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);
12640         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12641
12642         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12643         {
12644                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12645                 {
12646                         if (layerindex == 0)
12647                                 GL_AlphaTest(true);
12648                         else
12649                         {
12650                                 GL_AlphaTest(false);
12651                                 GL_DepthFunc(GL_EQUAL);
12652                         }
12653                 }
12654                 GL_DepthMask(layer->depthmask && writedepth);
12655                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12656                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12657                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12658                 switch (layer->type)
12659                 {
12660                 case TEXTURELAYERTYPE_LITTEXTURE:
12661                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12662                         {
12663                                 // two-pass lit texture with 2x rgbscale
12664                                 // first the lightmap pass
12665                                 R_Mesh_TexBind(0, r_texture_white);
12666                                 R_Mesh_TexMatrix(0, NULL);
12667                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12668                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12669                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12670                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12671                                 else if (FAKELIGHT_ENABLED)
12672                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12673                                 else if (rsurface.uselightmaptexture)
12674                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12675                                 else
12676                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12677                                 // then apply the texture to it
12678                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12679                                 R_Mesh_TexBind(0, layer->texture);
12680                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12681                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12682                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12683                                 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);
12684                         }
12685                         else
12686                         {
12687                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12688                                 R_Mesh_TexBind(0, layer->texture);
12689                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12690                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12691                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12692                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12693                                         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);
12694                                 else
12695                                         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);
12696                         }
12697                         break;
12698                 case TEXTURELAYERTYPE_TEXTURE:
12699                         // singletexture unlit texture with transparency support
12700                         R_Mesh_TexBind(0, layer->texture);
12701                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12702                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12703                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12704                         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);
12705                         break;
12706                 case TEXTURELAYERTYPE_FOG:
12707                         // singletexture fogging
12708                         if (layer->texture)
12709                         {
12710                                 R_Mesh_TexBind(0, layer->texture);
12711                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12712                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12713                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12714                         }
12715                         else
12716                         {
12717                                 R_Mesh_TexBind(0, 0);
12718                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12719                         }
12720                         // generate a color array for the fog pass
12721                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12722                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12723                         RSurf_DrawBatch();
12724                         break;
12725                 default:
12726                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12727                 }
12728         }
12729         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12730         {
12731                 GL_DepthFunc(GL_LEQUAL);
12732                 GL_AlphaTest(false);
12733         }
12734 }
12735
12736 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12737 {
12738         int vi;
12739         int j;
12740         r_vertexgeneric_t *batchvertex;
12741         float c[4];
12742
12743         GL_AlphaTest(false);
12744         R_Mesh_ResetTextureState();
12745         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12746
12747         if(rsurface.texture && rsurface.texture->currentskinframe)
12748         {
12749                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12750                 c[3] *= rsurface.texture->currentalpha;
12751         }
12752         else
12753         {
12754                 c[0] = 1;
12755                 c[1] = 0;
12756                 c[2] = 1;
12757                 c[3] = 1;
12758         }
12759
12760         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12761         {
12762                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12763                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12764                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12765         }
12766
12767         // brighten it up (as texture value 127 means "unlit")
12768         c[0] *= 2 * r_refdef.view.colorscale;
12769         c[1] *= 2 * r_refdef.view.colorscale;
12770         c[2] *= 2 * r_refdef.view.colorscale;
12771
12772         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12773                 c[3] *= r_wateralpha.value;
12774
12775         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12776         {
12777                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12778                 GL_DepthMask(false);
12779         }
12780         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12781         {
12782                 GL_BlendFunc(GL_ONE, GL_ONE);
12783                 GL_DepthMask(false);
12784         }
12785         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12786         {
12787                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12788                 GL_DepthMask(false);
12789         }
12790         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12791         {
12792                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12793                 GL_DepthMask(false);
12794         }
12795         else
12796         {
12797                 GL_BlendFunc(GL_ONE, GL_ZERO);
12798                 GL_DepthMask(writedepth);
12799         }
12800
12801         if (r_showsurfaces.integer == 3)
12802         {
12803                 rsurface.passcolor4f = NULL;
12804
12805                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12806                 {
12807                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12808
12809                         rsurface.passcolor4f = NULL;
12810                         rsurface.passcolor4f_vertexbuffer = 0;
12811                         rsurface.passcolor4f_bufferoffset = 0;
12812                 }
12813                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12814                 {
12815                         qboolean applycolor = true;
12816                         float one = 1.0;
12817
12818                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12819
12820                         r_refdef.lightmapintensity = 1;
12821                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12822                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12823                 }
12824                 else if (FAKELIGHT_ENABLED)
12825                 {
12826                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12827
12828                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12829                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12830                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12831                 }
12832                 else
12833                 {
12834                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12835
12836                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12837                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12838                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12839                 }
12840
12841                 if(!rsurface.passcolor4f)
12842                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12843
12844                 RSurf_DrawBatch_GL11_ApplyAmbient();
12845                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12846                 if(r_refdef.fogenabled)
12847                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12848                 RSurf_DrawBatch_GL11_ClampColor();
12849
12850                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12851                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12852                 RSurf_DrawBatch();
12853         }
12854         else if (!r_refdef.view.showdebug)
12855         {
12856                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12857                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12858                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12859                 {
12860                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12861                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12862                 }
12863                 R_Mesh_PrepareVertices_Generic_Unlock();
12864                 RSurf_DrawBatch();
12865         }
12866         else if (r_showsurfaces.integer == 4)
12867         {
12868                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12869                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12870                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12871                 {
12872                         unsigned char c = vi << 3;
12873                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12874                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12875                 }
12876                 R_Mesh_PrepareVertices_Generic_Unlock();
12877                 RSurf_DrawBatch();
12878         }
12879         else if (r_showsurfaces.integer == 2)
12880         {
12881                 const int *e;
12882                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12883                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12884                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12885                 {
12886                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12887                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12888                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12889                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12890                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12891                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12892                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12893                 }
12894                 R_Mesh_PrepareVertices_Generic_Unlock();
12895                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12896         }
12897         else
12898         {
12899                 int texturesurfaceindex;
12900                 int k;
12901                 const msurface_t *surface;
12902                 unsigned char surfacecolor4ub[4];
12903                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12904                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12905                 vi = 0;
12906                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12907                 {
12908                         surface = texturesurfacelist[texturesurfaceindex];
12909                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12910                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12911                         for (j = 0;j < surface->num_vertices;j++)
12912                         {
12913                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12914                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12915                                 vi++;
12916                         }
12917                 }
12918                 R_Mesh_PrepareVertices_Generic_Unlock();
12919                 RSurf_DrawBatch();
12920         }
12921 }
12922
12923 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12924 {
12925         CHECKGLERROR
12926         RSurf_SetupDepthAndCulling();
12927         if (r_showsurfaces.integer)
12928         {
12929                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12930                 return;
12931         }
12932         switch (vid.renderpath)
12933         {
12934         case RENDERPATH_GL20:
12935         case RENDERPATH_CGGL:
12936         case RENDERPATH_D3D9:
12937         case RENDERPATH_D3D10:
12938         case RENDERPATH_D3D11:
12939                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12940                 break;
12941         case RENDERPATH_GL13:
12942                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12943                 break;
12944         case RENDERPATH_GL11:
12945                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12946                 break;
12947         }
12948         CHECKGLERROR
12949 }
12950
12951 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12952 {
12953         CHECKGLERROR
12954         RSurf_SetupDepthAndCulling();
12955         if (r_showsurfaces.integer)
12956         {
12957                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12958                 return;
12959         }
12960         switch (vid.renderpath)
12961         {
12962         case RENDERPATH_GL20:
12963         case RENDERPATH_CGGL:
12964         case RENDERPATH_D3D9:
12965         case RENDERPATH_D3D10:
12966         case RENDERPATH_D3D11:
12967                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12968                 break;
12969         case RENDERPATH_GL13:
12970                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12971                 break;
12972         case RENDERPATH_GL11:
12973                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12974                 break;
12975         }
12976         CHECKGLERROR
12977 }
12978
12979 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12980 {
12981         int i, j;
12982         int texturenumsurfaces, endsurface;
12983         texture_t *texture;
12984         const msurface_t *surface;
12985 #define MAXBATCH_TRANSPARENTSURFACES 256
12986         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12987
12988         // if the model is static it doesn't matter what value we give for
12989         // wantnormals and wanttangents, so this logic uses only rules applicable
12990         // to a model, knowing that they are meaningless otherwise
12991         if (ent == r_refdef.scene.worldentity)
12992                 RSurf_ActiveWorldEntity();
12993         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12994                 RSurf_ActiveModelEntity(ent, false, false, false);
12995         else
12996         {
12997                 switch (vid.renderpath)
12998                 {
12999                 case RENDERPATH_GL20:
13000                 case RENDERPATH_CGGL:
13001                 case RENDERPATH_D3D9:
13002                 case RENDERPATH_D3D10:
13003                 case RENDERPATH_D3D11:
13004                         RSurf_ActiveModelEntity(ent, true, true, false);
13005                         break;
13006                 case RENDERPATH_GL13:
13007                 case RENDERPATH_GL11:
13008                         RSurf_ActiveModelEntity(ent, true, false, false);
13009                         break;
13010                 }
13011         }
13012
13013         if (r_transparentdepthmasking.integer)
13014         {
13015                 qboolean setup = false;
13016                 for (i = 0;i < numsurfaces;i = j)
13017                 {
13018                         j = i + 1;
13019                         surface = rsurface.modelsurfaces + surfacelist[i];
13020                         texture = surface->texture;
13021                         rsurface.texture = R_GetCurrentTexture(texture);
13022                         rsurface.lightmaptexture = NULL;
13023                         rsurface.deluxemaptexture = NULL;
13024                         rsurface.uselightmaptexture = false;
13025                         // scan ahead until we find a different texture
13026                         endsurface = min(i + 1024, numsurfaces);
13027                         texturenumsurfaces = 0;
13028                         texturesurfacelist[texturenumsurfaces++] = surface;
13029                         for (;j < endsurface;j++)
13030                         {
13031                                 surface = rsurface.modelsurfaces + surfacelist[j];
13032                                 if (texture != surface->texture)
13033                                         break;
13034                                 texturesurfacelist[texturenumsurfaces++] = surface;
13035                         }
13036                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13037                                 continue;
13038                         // render the range of surfaces as depth
13039                         if (!setup)
13040                         {
13041                                 setup = true;
13042                                 GL_ColorMask(0,0,0,0);
13043                                 GL_Color(1,1,1,1);
13044                                 GL_DepthTest(true);
13045                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13046                                 GL_DepthMask(true);
13047                                 GL_AlphaTest(false);
13048                                 R_Mesh_ResetTextureState();
13049                                 R_SetupShader_DepthOrShadow();
13050                         }
13051                         RSurf_SetupDepthAndCulling();
13052                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13053                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13054                         RSurf_DrawBatch();
13055                 }
13056                 if (setup)
13057                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13058         }
13059
13060         for (i = 0;i < numsurfaces;i = j)
13061         {
13062                 j = i + 1;
13063                 surface = rsurface.modelsurfaces + surfacelist[i];
13064                 texture = surface->texture;
13065                 rsurface.texture = R_GetCurrentTexture(texture);
13066                 // scan ahead until we find a different texture
13067                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13068                 texturenumsurfaces = 0;
13069                 texturesurfacelist[texturenumsurfaces++] = surface;
13070                 if(FAKELIGHT_ENABLED)
13071                 {
13072                         rsurface.lightmaptexture = NULL;
13073                         rsurface.deluxemaptexture = NULL;
13074                         rsurface.uselightmaptexture = false;
13075                         for (;j < endsurface;j++)
13076                         {
13077                                 surface = rsurface.modelsurfaces + surfacelist[j];
13078                                 if (texture != surface->texture)
13079                                         break;
13080                                 texturesurfacelist[texturenumsurfaces++] = surface;
13081                         }
13082                 }
13083                 else
13084                 {
13085                         rsurface.lightmaptexture = surface->lightmaptexture;
13086                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13087                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13088                         for (;j < endsurface;j++)
13089                         {
13090                                 surface = rsurface.modelsurfaces + surfacelist[j];
13091                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13092                                         break;
13093                                 texturesurfacelist[texturenumsurfaces++] = surface;
13094                         }
13095                 }
13096                 // render the range of surfaces
13097                 if (ent == r_refdef.scene.worldentity)
13098                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13099                 else
13100                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13101         }
13102         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13103         GL_AlphaTest(false);
13104 }
13105
13106 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13107 {
13108         // transparent surfaces get pushed off into the transparent queue
13109         int surfacelistindex;
13110         const msurface_t *surface;
13111         vec3_t tempcenter, center;
13112         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13113         {
13114                 surface = texturesurfacelist[surfacelistindex];
13115                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13116                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13117                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13118                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13119                 if (queueentity->transparent_offset) // transparent offset
13120                 {
13121                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13122                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13123                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13124                 }
13125                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13126         }
13127 }
13128
13129 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13130 {
13131         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13132                 return;
13133         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13134                 return;
13135         RSurf_SetupDepthAndCulling();
13136         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13137         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13138         RSurf_DrawBatch();
13139 }
13140
13141 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13142 {
13143         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13144         CHECKGLERROR
13145         if (depthonly)
13146                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13147         else if (prepass)
13148         {
13149                 if (!rsurface.texture->currentnumlayers)
13150                         return;
13151                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13152                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13153                 else
13154                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13155         }
13156         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13157                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13158         else if (!rsurface.texture->currentnumlayers)
13159                 return;
13160         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13161         {
13162                 // in the deferred case, transparent surfaces were queued during prepass
13163                 if (!r_shadow_usingdeferredprepass)
13164                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13165         }
13166         else
13167         {
13168                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13169                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13170         }
13171         CHECKGLERROR
13172 }
13173
13174 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13175 {
13176         int i, j;
13177         texture_t *texture;
13178         // break the surface list down into batches by texture and use of lightmapping
13179         for (i = 0;i < numsurfaces;i = j)
13180         {
13181                 j = i + 1;
13182                 // texture is the base texture pointer, rsurface.texture is the
13183                 // current frame/skin the texture is directing us to use (for example
13184                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13185                 // use skin 1 instead)
13186                 texture = surfacelist[i]->texture;
13187                 rsurface.texture = R_GetCurrentTexture(texture);
13188                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13189                 {
13190                         // if this texture is not the kind we want, skip ahead to the next one
13191                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13192                                 ;
13193                         continue;
13194                 }
13195                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13196                 {
13197                         rsurface.lightmaptexture = NULL;
13198                         rsurface.deluxemaptexture = NULL;
13199                         rsurface.uselightmaptexture = false;
13200                         // simply scan ahead until we find a different texture or lightmap state
13201                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13202                                 ;
13203                 }
13204                 else
13205                 {
13206                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13207                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13208                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13209                         // simply scan ahead until we find a different texture or lightmap state
13210                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13211                                 ;
13212                 }
13213                 // render the range of surfaces
13214                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13215         }
13216 }
13217
13218 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13219 {
13220         CHECKGLERROR
13221         if (depthonly)
13222                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13223         else if (prepass)
13224         {
13225                 if (!rsurface.texture->currentnumlayers)
13226                         return;
13227                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13228                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13229                 else
13230                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13231         }
13232         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13233                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13234         else if (!rsurface.texture->currentnumlayers)
13235                 return;
13236         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13237         {
13238                 // in the deferred case, transparent surfaces were queued during prepass
13239                 if (!r_shadow_usingdeferredprepass)
13240                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13241         }
13242         else
13243         {
13244                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13245                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13246         }
13247         CHECKGLERROR
13248 }
13249
13250 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13251 {
13252         int i, j;
13253         texture_t *texture;
13254         // break the surface list down into batches by texture and use of lightmapping
13255         for (i = 0;i < numsurfaces;i = j)
13256         {
13257                 j = i + 1;
13258                 // texture is the base texture pointer, rsurface.texture is the
13259                 // current frame/skin the texture is directing us to use (for example
13260                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13261                 // use skin 1 instead)
13262                 texture = surfacelist[i]->texture;
13263                 rsurface.texture = R_GetCurrentTexture(texture);
13264                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13265                 {
13266                         // if this texture is not the kind we want, skip ahead to the next one
13267                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13268                                 ;
13269                         continue;
13270                 }
13271                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13272                 {
13273                         rsurface.lightmaptexture = NULL;
13274                         rsurface.deluxemaptexture = NULL;
13275                         rsurface.uselightmaptexture = false;
13276                         // simply scan ahead until we find a different texture or lightmap state
13277                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13278                                 ;
13279                 }
13280                 else
13281                 {
13282                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13283                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13284                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13285                         // simply scan ahead until we find a different texture or lightmap state
13286                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13287                                 ;
13288                 }
13289                 // render the range of surfaces
13290                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13291         }
13292 }
13293
13294 float locboxvertex3f[6*4*3] =
13295 {
13296         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13297         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13298         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13299         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13300         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13301         1,0,0, 0,0,0, 0,1,0, 1,1,0
13302 };
13303
13304 unsigned short locboxelements[6*2*3] =
13305 {
13306          0, 1, 2, 0, 2, 3,
13307          4, 5, 6, 4, 6, 7,
13308          8, 9,10, 8,10,11,
13309         12,13,14, 12,14,15,
13310         16,17,18, 16,18,19,
13311         20,21,22, 20,22,23
13312 };
13313
13314 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13315 {
13316         int i, j;
13317         cl_locnode_t *loc = (cl_locnode_t *)ent;
13318         vec3_t mins, size;
13319         float vertex3f[6*4*3];
13320         CHECKGLERROR
13321         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13322         GL_DepthMask(false);
13323         GL_DepthRange(0, 1);
13324         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13325         GL_DepthTest(true);
13326         GL_CullFace(GL_NONE);
13327         R_EntityMatrix(&identitymatrix);
13328
13329         R_Mesh_ResetTextureState();
13330
13331         i = surfacelist[0];
13332         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13333                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13334                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13335                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13336
13337         if (VectorCompare(loc->mins, loc->maxs))
13338         {
13339                 VectorSet(size, 2, 2, 2);
13340                 VectorMA(loc->mins, -0.5f, size, mins);
13341         }
13342         else
13343         {
13344                 VectorCopy(loc->mins, mins);
13345                 VectorSubtract(loc->maxs, loc->mins, size);
13346         }
13347
13348         for (i = 0;i < 6*4*3;)
13349                 for (j = 0;j < 3;j++, i++)
13350                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13351
13352         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13353         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13354         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13355 }
13356
13357 void R_DrawLocs(void)
13358 {
13359         int index;
13360         cl_locnode_t *loc, *nearestloc;
13361         vec3_t center;
13362         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13363         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13364         {
13365                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13366                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13367         }
13368 }
13369
13370 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13371 {
13372         if (decalsystem->decals)
13373                 Mem_Free(decalsystem->decals);
13374         memset(decalsystem, 0, sizeof(*decalsystem));
13375 }
13376
13377 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)
13378 {
13379         tridecal_t *decal;
13380         tridecal_t *decals;
13381         int i;
13382
13383         // expand or initialize the system
13384         if (decalsystem->maxdecals <= decalsystem->numdecals)
13385         {
13386                 decalsystem_t old = *decalsystem;
13387                 qboolean useshortelements;
13388                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13389                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13390                 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)));
13391                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13392                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13393                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13394                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13395                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13396                 if (decalsystem->numdecals)
13397                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13398                 if (old.decals)
13399                         Mem_Free(old.decals);
13400                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13401                         decalsystem->element3i[i] = i;
13402                 if (useshortelements)
13403                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13404                                 decalsystem->element3s[i] = i;
13405         }
13406
13407         // grab a decal and search for another free slot for the next one
13408         decals = decalsystem->decals;
13409         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13410         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13411                 ;
13412         decalsystem->freedecal = i;
13413         if (decalsystem->numdecals <= i)
13414                 decalsystem->numdecals = i + 1;
13415
13416         // initialize the decal
13417         decal->lived = 0;
13418         decal->triangleindex = triangleindex;
13419         decal->surfaceindex = surfaceindex;
13420         decal->decalsequence = decalsequence;
13421         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13422         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13423         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13424         decal->color4ub[0][3] = 255;
13425         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13426         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13427         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13428         decal->color4ub[1][3] = 255;
13429         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13430         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13431         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13432         decal->color4ub[2][3] = 255;
13433         decal->vertex3f[0][0] = v0[0];
13434         decal->vertex3f[0][1] = v0[1];
13435         decal->vertex3f[0][2] = v0[2];
13436         decal->vertex3f[1][0] = v1[0];
13437         decal->vertex3f[1][1] = v1[1];
13438         decal->vertex3f[1][2] = v1[2];
13439         decal->vertex3f[2][0] = v2[0];
13440         decal->vertex3f[2][1] = v2[1];
13441         decal->vertex3f[2][2] = v2[2];
13442         decal->texcoord2f[0][0] = t0[0];
13443         decal->texcoord2f[0][1] = t0[1];
13444         decal->texcoord2f[1][0] = t1[0];
13445         decal->texcoord2f[1][1] = t1[1];
13446         decal->texcoord2f[2][0] = t2[0];
13447         decal->texcoord2f[2][1] = t2[1];
13448 }
13449
13450 extern cvar_t cl_decals_bias;
13451 extern cvar_t cl_decals_models;
13452 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13453 // baseparms, parms, temps
13454 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)
13455 {
13456         int cornerindex;
13457         int index;
13458         float v[9][3];
13459         const float *vertex3f;
13460         int numpoints;
13461         float points[2][9][3];
13462         float temp[3];
13463         float tc[9][2];
13464         float f;
13465         float c[9][4];
13466         const int *e;
13467
13468         e = rsurface.modelelement3i + 3*triangleindex;
13469
13470         vertex3f = rsurface.modelvertex3f;
13471
13472         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13473         {
13474                 index = 3*e[cornerindex];
13475                 VectorCopy(vertex3f + index, v[cornerindex]);
13476         }
13477         // cull backfaces
13478         //TriangleNormal(v[0], v[1], v[2], normal);
13479         //if (DotProduct(normal, localnormal) < 0.0f)
13480         //      continue;
13481         // clip by each of the box planes formed from the projection matrix
13482         // if anything survives, we emit the decal
13483         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]);
13484         if (numpoints < 3)
13485                 return;
13486         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]);
13487         if (numpoints < 3)
13488                 return;
13489         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]);
13490         if (numpoints < 3)
13491                 return;
13492         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]);
13493         if (numpoints < 3)
13494                 return;
13495         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]);
13496         if (numpoints < 3)
13497                 return;
13498         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]);
13499         if (numpoints < 3)
13500                 return;
13501         // some part of the triangle survived, so we have to accept it...
13502         if (dynamic)
13503         {
13504                 // dynamic always uses the original triangle
13505                 numpoints = 3;
13506                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13507                 {
13508                         index = 3*e[cornerindex];
13509                         VectorCopy(vertex3f + index, v[cornerindex]);
13510                 }
13511         }
13512         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13513         {
13514                 // convert vertex positions to texcoords
13515                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13516                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13517                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13518                 // calculate distance fade from the projection origin
13519                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13520                 f = bound(0.0f, f, 1.0f);
13521                 c[cornerindex][0] = r * f;
13522                 c[cornerindex][1] = g * f;
13523                 c[cornerindex][2] = b * f;
13524                 c[cornerindex][3] = 1.0f;
13525                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13526         }
13527         if (dynamic)
13528                 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);
13529         else
13530                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13531                         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);
13532 }
13533 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)
13534 {
13535         matrix4x4_t projection;
13536         decalsystem_t *decalsystem;
13537         qboolean dynamic;
13538         dp_model_t *model;
13539         const msurface_t *surface;
13540         const msurface_t *surfaces;
13541         const int *surfacelist;
13542         const texture_t *texture;
13543         int numtriangles;
13544         int numsurfacelist;
13545         int surfacelistindex;
13546         int surfaceindex;
13547         int triangleindex;
13548         float localorigin[3];
13549         float localnormal[3];
13550         float localmins[3];
13551         float localmaxs[3];
13552         float localsize;
13553         //float normal[3];
13554         float planes[6][4];
13555         float angles[3];
13556         bih_t *bih;
13557         int bih_triangles_count;
13558         int bih_triangles[256];
13559         int bih_surfaces[256];
13560
13561         decalsystem = &ent->decalsystem;
13562         model = ent->model;
13563         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13564         {
13565                 R_DecalSystem_Reset(&ent->decalsystem);
13566                 return;
13567         }
13568
13569         if (!model->brush.data_leafs && !cl_decals_models.integer)
13570         {
13571                 if (decalsystem->model)
13572                         R_DecalSystem_Reset(decalsystem);
13573                 return;
13574         }
13575
13576         if (decalsystem->model != model)
13577                 R_DecalSystem_Reset(decalsystem);
13578         decalsystem->model = model;
13579
13580         RSurf_ActiveModelEntity(ent, false, false, false);
13581
13582         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13583         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13584         VectorNormalize(localnormal);
13585         localsize = worldsize*rsurface.inversematrixscale;
13586         localmins[0] = localorigin[0] - localsize;
13587         localmins[1] = localorigin[1] - localsize;
13588         localmins[2] = localorigin[2] - localsize;
13589         localmaxs[0] = localorigin[0] + localsize;
13590         localmaxs[1] = localorigin[1] + localsize;
13591         localmaxs[2] = localorigin[2] + localsize;
13592
13593         //VectorCopy(localnormal, planes[4]);
13594         //VectorVectors(planes[4], planes[2], planes[0]);
13595         AnglesFromVectors(angles, localnormal, NULL, false);
13596         AngleVectors(angles, planes[0], planes[2], planes[4]);
13597         VectorNegate(planes[0], planes[1]);
13598         VectorNegate(planes[2], planes[3]);
13599         VectorNegate(planes[4], planes[5]);
13600         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13601         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13602         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13603         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13604         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13605         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13606
13607 #if 1
13608 // works
13609 {
13610         matrix4x4_t forwardprojection;
13611         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13612         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13613 }
13614 #else
13615 // broken
13616 {
13617         float projectionvector[4][3];
13618         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13619         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13620         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13621         projectionvector[0][0] = planes[0][0] * ilocalsize;
13622         projectionvector[0][1] = planes[1][0] * ilocalsize;
13623         projectionvector[0][2] = planes[2][0] * ilocalsize;
13624         projectionvector[1][0] = planes[0][1] * ilocalsize;
13625         projectionvector[1][1] = planes[1][1] * ilocalsize;
13626         projectionvector[1][2] = planes[2][1] * ilocalsize;
13627         projectionvector[2][0] = planes[0][2] * ilocalsize;
13628         projectionvector[2][1] = planes[1][2] * ilocalsize;
13629         projectionvector[2][2] = planes[2][2] * ilocalsize;
13630         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13631         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13632         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13633         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13634 }
13635 #endif
13636
13637         dynamic = model->surfmesh.isanimated;
13638         numsurfacelist = model->nummodelsurfaces;
13639         surfacelist = model->sortedmodelsurfaces;
13640         surfaces = model->data_surfaces;
13641
13642         bih = NULL;
13643         bih_triangles_count = -1;
13644         if(!dynamic)
13645         {
13646                 if(model->render_bih.numleafs)
13647                         bih = &model->render_bih;
13648                 else if(model->collision_bih.numleafs)
13649                         bih = &model->collision_bih;
13650         }
13651         if(bih)
13652                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13653         if(bih_triangles_count == 0)
13654                 return;
13655         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13656                 return;
13657         if(bih_triangles_count > 0)
13658         {
13659                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13660                 {
13661                         surfaceindex = bih_surfaces[triangleindex];
13662                         surface = surfaces + surfaceindex;
13663                         texture = surface->texture;
13664                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13665                                 continue;
13666                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13667                                 continue;
13668                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13669                 }
13670         }
13671         else
13672         {
13673                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13674                 {
13675                         surfaceindex = surfacelist[surfacelistindex];
13676                         surface = surfaces + surfaceindex;
13677                         // check cull box first because it rejects more than any other check
13678                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13679                                 continue;
13680                         // skip transparent surfaces
13681                         texture = surface->texture;
13682                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13683                                 continue;
13684                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13685                                 continue;
13686                         numtriangles = surface->num_triangles;
13687                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13688                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13689                 }
13690         }
13691 }
13692
13693 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13694 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)
13695 {
13696         int renderentityindex;
13697         float worldmins[3];
13698         float worldmaxs[3];
13699         entity_render_t *ent;
13700
13701         if (!cl_decals_newsystem.integer)
13702                 return;
13703
13704         worldmins[0] = worldorigin[0] - worldsize;
13705         worldmins[1] = worldorigin[1] - worldsize;
13706         worldmins[2] = worldorigin[2] - worldsize;
13707         worldmaxs[0] = worldorigin[0] + worldsize;
13708         worldmaxs[1] = worldorigin[1] + worldsize;
13709         worldmaxs[2] = worldorigin[2] + worldsize;
13710
13711         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13712
13713         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13714         {
13715                 ent = r_refdef.scene.entities[renderentityindex];
13716                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13717                         continue;
13718
13719                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13720         }
13721 }
13722
13723 typedef struct r_decalsystem_splatqueue_s
13724 {
13725         vec3_t worldorigin;
13726         vec3_t worldnormal;
13727         float color[4];
13728         float tcrange[4];
13729         float worldsize;
13730         int decalsequence;
13731 }
13732 r_decalsystem_splatqueue_t;
13733
13734 int r_decalsystem_numqueued = 0;
13735 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13736
13737 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)
13738 {
13739         r_decalsystem_splatqueue_t *queue;
13740
13741         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13742                 return;
13743
13744         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13745         VectorCopy(worldorigin, queue->worldorigin);
13746         VectorCopy(worldnormal, queue->worldnormal);
13747         Vector4Set(queue->color, r, g, b, a);
13748         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13749         queue->worldsize = worldsize;
13750         queue->decalsequence = cl.decalsequence++;
13751 }
13752
13753 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13754 {
13755         int i;
13756         r_decalsystem_splatqueue_t *queue;
13757
13758         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13759                 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);
13760         r_decalsystem_numqueued = 0;
13761 }
13762
13763 extern cvar_t cl_decals_max;
13764 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13765 {
13766         int i;
13767         decalsystem_t *decalsystem = &ent->decalsystem;
13768         int numdecals;
13769         int killsequence;
13770         tridecal_t *decal;
13771         float frametime;
13772         float lifetime;
13773
13774         if (!decalsystem->numdecals)
13775                 return;
13776
13777         if (r_showsurfaces.integer)
13778                 return;
13779
13780         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13781         {
13782                 R_DecalSystem_Reset(decalsystem);
13783                 return;
13784         }
13785
13786         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13787         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13788
13789         if (decalsystem->lastupdatetime)
13790                 frametime = (cl.time - decalsystem->lastupdatetime);
13791         else
13792                 frametime = 0;
13793         decalsystem->lastupdatetime = cl.time;
13794         decal = decalsystem->decals;
13795         numdecals = decalsystem->numdecals;
13796
13797         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13798         {
13799                 if (decal->color4ub[0][3])
13800                 {
13801                         decal->lived += frametime;
13802                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13803                         {
13804                                 memset(decal, 0, sizeof(*decal));
13805                                 if (decalsystem->freedecal > i)
13806                                         decalsystem->freedecal = i;
13807                         }
13808                 }
13809         }
13810         decal = decalsystem->decals;
13811         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13812                 numdecals--;
13813
13814         // collapse the array by shuffling the tail decals into the gaps
13815         for (;;)
13816         {
13817                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13818                         decalsystem->freedecal++;
13819                 if (decalsystem->freedecal == numdecals)
13820                         break;
13821                 decal[decalsystem->freedecal] = decal[--numdecals];
13822         }
13823
13824         decalsystem->numdecals = numdecals;
13825
13826         if (numdecals <= 0)
13827         {
13828                 // if there are no decals left, reset decalsystem
13829                 R_DecalSystem_Reset(decalsystem);
13830         }
13831 }
13832
13833 extern skinframe_t *decalskinframe;
13834 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13835 {
13836         int i;
13837         decalsystem_t *decalsystem = &ent->decalsystem;
13838         int numdecals;
13839         tridecal_t *decal;
13840         float faderate;
13841         float alpha;
13842         float *v3f;
13843         float *c4f;
13844         float *t2f;
13845         const int *e;
13846         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13847         int numtris = 0;
13848
13849         numdecals = decalsystem->numdecals;
13850         if (!numdecals)
13851                 return;
13852
13853         if (r_showsurfaces.integer)
13854                 return;
13855
13856         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13857         {
13858                 R_DecalSystem_Reset(decalsystem);
13859                 return;
13860         }
13861
13862         // if the model is static it doesn't matter what value we give for
13863         // wantnormals and wanttangents, so this logic uses only rules applicable
13864         // to a model, knowing that they are meaningless otherwise
13865         if (ent == r_refdef.scene.worldentity)
13866                 RSurf_ActiveWorldEntity();
13867         else
13868                 RSurf_ActiveModelEntity(ent, false, false, false);
13869
13870         decalsystem->lastupdatetime = cl.time;
13871         decal = decalsystem->decals;
13872
13873         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13874
13875         // update vertex positions for animated models
13876         v3f = decalsystem->vertex3f;
13877         c4f = decalsystem->color4f;
13878         t2f = decalsystem->texcoord2f;
13879         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13880         {
13881                 if (!decal->color4ub[0][3])
13882                         continue;
13883
13884                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13885                         continue;
13886
13887                 // update color values for fading decals
13888                 if (decal->lived >= cl_decals_time.value)
13889                 {
13890                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13891                         alpha *= (1.0f/255.0f);
13892                 }
13893                 else
13894                         alpha = 1.0f/255.0f;
13895
13896                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13897                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13898                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13899                 c4f[ 3] = 1;
13900                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13901                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13902                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13903                 c4f[ 7] = 1;
13904                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13905                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13906                 c4f[10] = decal->color4ub[2][2] * alpha;
13907                 c4f[11] = 1;
13908
13909                 t2f[0] = decal->texcoord2f[0][0];
13910                 t2f[1] = decal->texcoord2f[0][1];
13911                 t2f[2] = decal->texcoord2f[1][0];
13912                 t2f[3] = decal->texcoord2f[1][1];
13913                 t2f[4] = decal->texcoord2f[2][0];
13914                 t2f[5] = decal->texcoord2f[2][1];
13915
13916                 // update vertex positions for animated models
13917                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13918                 {
13919                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13920                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13921                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13922                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13923                 }
13924                 else
13925                 {
13926                         VectorCopy(decal->vertex3f[0], v3f);
13927                         VectorCopy(decal->vertex3f[1], v3f + 3);
13928                         VectorCopy(decal->vertex3f[2], v3f + 6);
13929                 }
13930
13931                 if (r_refdef.fogenabled)
13932                 {
13933                         alpha = RSurf_FogVertex(v3f);
13934                         VectorScale(c4f, alpha, c4f);
13935                         alpha = RSurf_FogVertex(v3f + 3);
13936                         VectorScale(c4f + 4, alpha, c4f + 4);
13937                         alpha = RSurf_FogVertex(v3f + 6);
13938                         VectorScale(c4f + 8, alpha, c4f + 8);
13939                 }
13940
13941                 v3f += 9;
13942                 c4f += 12;
13943                 t2f += 6;
13944                 numtris++;
13945         }
13946
13947         if (numtris > 0)
13948         {
13949                 r_refdef.stats.drawndecals += numtris;
13950
13951                 // now render the decals all at once
13952                 // (this assumes they all use one particle font texture!)
13953                 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);
13954                 R_Mesh_ResetTextureState();
13955                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13956                 GL_DepthMask(false);
13957                 GL_DepthRange(0, 1);
13958                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13959                 GL_DepthTest(true);
13960                 GL_CullFace(GL_NONE);
13961                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13962                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13963                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13964         }
13965 }
13966
13967 static void R_DrawModelDecals(void)
13968 {
13969         int i, numdecals;
13970
13971         // fade faster when there are too many decals
13972         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13973         for (i = 0;i < r_refdef.scene.numentities;i++)
13974                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13975
13976         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13977         for (i = 0;i < r_refdef.scene.numentities;i++)
13978                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13979                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13980
13981         R_DecalSystem_ApplySplatEntitiesQueue();
13982
13983         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13984         for (i = 0;i < r_refdef.scene.numentities;i++)
13985                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13986
13987         r_refdef.stats.totaldecals += numdecals;
13988
13989         if (r_showsurfaces.integer)
13990                 return;
13991
13992         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13993
13994         for (i = 0;i < r_refdef.scene.numentities;i++)
13995         {
13996                 if (!r_refdef.viewcache.entityvisible[i])
13997                         continue;
13998                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13999                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14000         }
14001 }
14002
14003 extern cvar_t mod_collision_bih;
14004 void R_DrawDebugModel(void)
14005 {
14006         entity_render_t *ent = rsurface.entity;
14007         int i, j, k, l, flagsmask;
14008         const msurface_t *surface;
14009         dp_model_t *model = ent->model;
14010         vec3_t v;
14011
14012         switch(vid.renderpath)
14013         {
14014         case RENDERPATH_GL11:
14015         case RENDERPATH_GL13:
14016         case RENDERPATH_GL20:
14017         case RENDERPATH_CGGL:
14018                 break;
14019         case RENDERPATH_D3D9:
14020                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14021                 return;
14022         case RENDERPATH_D3D10:
14023                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14024                 return;
14025         case RENDERPATH_D3D11:
14026                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14027                 return;
14028         }
14029
14030         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14031
14032         R_Mesh_ResetTextureState();
14033         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14034         GL_DepthRange(0, 1);
14035         GL_DepthTest(!r_showdisabledepthtest.integer);
14036         GL_DepthMask(false);
14037         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14038
14039         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14040         {
14041                 int triangleindex;
14042                 int bihleafindex;
14043                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14044                 const q3mbrush_t *brush;
14045                 const bih_t *bih = &model->collision_bih;
14046                 const bih_leaf_t *bihleaf;
14047                 float vertex3f[3][3];
14048                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14049                 cullbox = false;
14050                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14051                 {
14052                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14053                                 continue;
14054                         switch (bihleaf->type)
14055                         {
14056                         case BIH_BRUSH:
14057                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14058                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14059                                 {
14060                                         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);
14061                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14062                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14063                                 }
14064                                 break;
14065                         case BIH_COLLISIONTRIANGLE:
14066                                 triangleindex = bihleaf->itemindex;
14067                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14068                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14069                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14070                                 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);
14071                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14072                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14073                                 break;
14074                         case BIH_RENDERTRIANGLE:
14075                                 triangleindex = bihleaf->itemindex;
14076                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14077                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14078                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14079                                 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);
14080                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14081                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14082                                 break;
14083                         }
14084                 }
14085         }
14086
14087         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14088
14089         if (r_showtris.integer || r_shownormals.integer)
14090         {
14091                 if (r_showdisabledepthtest.integer)
14092                 {
14093                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14094                         GL_DepthMask(false);
14095                 }
14096                 else
14097                 {
14098                         GL_BlendFunc(GL_ONE, GL_ZERO);
14099                         GL_DepthMask(true);
14100                 }
14101                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14102                 {
14103                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14104                                 continue;
14105                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14106                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14107                         {
14108                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14109                                 if (r_showtris.value > 0)
14110                                 {
14111                                         if (!rsurface.texture->currentlayers->depthmask)
14112                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14113                                         else if (ent == r_refdef.scene.worldentity)
14114                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14115                                         else
14116                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14117                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14118                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14119                                         RSurf_DrawBatch();
14120                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14121                                         CHECKGLERROR
14122                                 }
14123                                 if (r_shownormals.value < 0)
14124                                 {
14125                                         qglBegin(GL_LINES);
14126                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14127                                         {
14128                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14129                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14130                                                 qglVertex3f(v[0], v[1], v[2]);
14131                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14132                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14133                                                 qglVertex3f(v[0], v[1], v[2]);
14134                                         }
14135                                         qglEnd();
14136                                         CHECKGLERROR
14137                                 }
14138                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14139                                 {
14140                                         qglBegin(GL_LINES);
14141                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14142                                         {
14143                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14144                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14145                                                 qglVertex3f(v[0], v[1], v[2]);
14146                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14147                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14148                                                 qglVertex3f(v[0], v[1], v[2]);
14149                                         }
14150                                         qglEnd();
14151                                         CHECKGLERROR
14152                                         qglBegin(GL_LINES);
14153                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14154                                         {
14155                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14156                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14157                                                 qglVertex3f(v[0], v[1], v[2]);
14158                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14159                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14160                                                 qglVertex3f(v[0], v[1], v[2]);
14161                                         }
14162                                         qglEnd();
14163                                         CHECKGLERROR
14164                                         qglBegin(GL_LINES);
14165                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14166                                         {
14167                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14168                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14169                                                 qglVertex3f(v[0], v[1], v[2]);
14170                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14171                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14172                                                 qglVertex3f(v[0], v[1], v[2]);
14173                                         }
14174                                         qglEnd();
14175                                         CHECKGLERROR
14176                                 }
14177                         }
14178                 }
14179                 rsurface.texture = NULL;
14180         }
14181 }
14182
14183 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14184 int r_maxsurfacelist = 0;
14185 const msurface_t **r_surfacelist = NULL;
14186 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14187 {
14188         int i, j, endj, flagsmask;
14189         dp_model_t *model = r_refdef.scene.worldmodel;
14190         msurface_t *surfaces;
14191         unsigned char *update;
14192         int numsurfacelist = 0;
14193         if (model == NULL)
14194                 return;
14195
14196         if (r_maxsurfacelist < model->num_surfaces)
14197         {
14198                 r_maxsurfacelist = model->num_surfaces;
14199                 if (r_surfacelist)
14200                         Mem_Free((msurface_t**)r_surfacelist);
14201                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14202         }
14203
14204         RSurf_ActiveWorldEntity();
14205
14206         surfaces = model->data_surfaces;
14207         update = model->brushq1.lightmapupdateflags;
14208
14209         // update light styles on this submodel
14210         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14211         {
14212                 model_brush_lightstyleinfo_t *style;
14213                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14214                 {
14215                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14216                         {
14217                                 int *list = style->surfacelist;
14218                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14219                                 for (j = 0;j < style->numsurfaces;j++)
14220                                         update[list[j]] = true;
14221                         }
14222                 }
14223         }
14224
14225         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14226
14227         if (debug)
14228         {
14229                 R_DrawDebugModel();
14230                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14231                 return;
14232         }
14233
14234         rsurface.lightmaptexture = NULL;
14235         rsurface.deluxemaptexture = NULL;
14236         rsurface.uselightmaptexture = false;
14237         rsurface.texture = NULL;
14238         rsurface.rtlight = NULL;
14239         numsurfacelist = 0;
14240         // add visible surfaces to draw list
14241         for (i = 0;i < model->nummodelsurfaces;i++)
14242         {
14243                 j = model->sortedmodelsurfaces[i];
14244                 if (r_refdef.viewcache.world_surfacevisible[j])
14245                         r_surfacelist[numsurfacelist++] = surfaces + j;
14246         }
14247         // update lightmaps if needed
14248         if (model->brushq1.firstrender)
14249         {
14250                 model->brushq1.firstrender = false;
14251                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14252                         if (update[j])
14253                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14254         }
14255         else if (update)
14256         {
14257                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14258                         if (r_refdef.viewcache.world_surfacevisible[j])
14259                                 if (update[j])
14260                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14261         }
14262         // don't do anything if there were no surfaces
14263         if (!numsurfacelist)
14264         {
14265                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14266                 return;
14267         }
14268         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14269         GL_AlphaTest(false);
14270
14271         // add to stats if desired
14272         if (r_speeds.integer && !skysurfaces && !depthonly)
14273         {
14274                 r_refdef.stats.world_surfaces += numsurfacelist;
14275                 for (j = 0;j < numsurfacelist;j++)
14276                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14277         }
14278
14279         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14280 }
14281
14282 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14283 {
14284         int i, j, endj, flagsmask;
14285         dp_model_t *model = ent->model;
14286         msurface_t *surfaces;
14287         unsigned char *update;
14288         int numsurfacelist = 0;
14289         if (model == NULL)
14290                 return;
14291
14292         if (r_maxsurfacelist < model->num_surfaces)
14293         {
14294                 r_maxsurfacelist = model->num_surfaces;
14295                 if (r_surfacelist)
14296                         Mem_Free((msurface_t **)r_surfacelist);
14297                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14298         }
14299
14300         // if the model is static it doesn't matter what value we give for
14301         // wantnormals and wanttangents, so this logic uses only rules applicable
14302         // to a model, knowing that they are meaningless otherwise
14303         if (ent == r_refdef.scene.worldentity)
14304                 RSurf_ActiveWorldEntity();
14305         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14306                 RSurf_ActiveModelEntity(ent, false, false, false);
14307         else if (prepass)
14308                 RSurf_ActiveModelEntity(ent, true, true, true);
14309         else if (depthonly)
14310         {
14311                 switch (vid.renderpath)
14312                 {
14313                 case RENDERPATH_GL20:
14314                 case RENDERPATH_CGGL:
14315                 case RENDERPATH_D3D9:
14316                 case RENDERPATH_D3D10:
14317                 case RENDERPATH_D3D11:
14318                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14319                         break;
14320                 case RENDERPATH_GL13:
14321                 case RENDERPATH_GL11:
14322                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14323                         break;
14324                 }
14325         }
14326         else
14327         {
14328                 switch (vid.renderpath)
14329                 {
14330                 case RENDERPATH_GL20:
14331                 case RENDERPATH_CGGL:
14332                 case RENDERPATH_D3D9:
14333                 case RENDERPATH_D3D10:
14334                 case RENDERPATH_D3D11:
14335                         RSurf_ActiveModelEntity(ent, true, true, false);
14336                         break;
14337                 case RENDERPATH_GL13:
14338                 case RENDERPATH_GL11:
14339                         RSurf_ActiveModelEntity(ent, true, false, false);
14340                         break;
14341                 }
14342         }
14343
14344         surfaces = model->data_surfaces;
14345         update = model->brushq1.lightmapupdateflags;
14346
14347         // update light styles
14348         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14349         {
14350                 model_brush_lightstyleinfo_t *style;
14351                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14352                 {
14353                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14354                         {
14355                                 int *list = style->surfacelist;
14356                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14357                                 for (j = 0;j < style->numsurfaces;j++)
14358                                         update[list[j]] = true;
14359                         }
14360                 }
14361         }
14362
14363         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14364
14365         if (debug)
14366         {
14367                 R_DrawDebugModel();
14368                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14369                 return;
14370         }
14371
14372         rsurface.lightmaptexture = NULL;
14373         rsurface.deluxemaptexture = NULL;
14374         rsurface.uselightmaptexture = false;
14375         rsurface.texture = NULL;
14376         rsurface.rtlight = NULL;
14377         numsurfacelist = 0;
14378         // add visible surfaces to draw list
14379         for (i = 0;i < model->nummodelsurfaces;i++)
14380                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14381         // don't do anything if there were no surfaces
14382         if (!numsurfacelist)
14383         {
14384                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14385                 return;
14386         }
14387         // update lightmaps if needed
14388         if (update)
14389         {
14390                 int updated = 0;
14391                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14392                 {
14393                         if (update[j])
14394                         {
14395                                 updated++;
14396                                 R_BuildLightMap(ent, surfaces + j);
14397                         }
14398                 }
14399         }
14400         if (update)
14401                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14402                         if (update[j])
14403                                 R_BuildLightMap(ent, surfaces + j);
14404         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14405         GL_AlphaTest(false);
14406
14407         // add to stats if desired
14408         if (r_speeds.integer && !skysurfaces && !depthonly)
14409         {
14410                 r_refdef.stats.entities_surfaces += numsurfacelist;
14411                 for (j = 0;j < numsurfacelist;j++)
14412                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14413         }
14414
14415         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14416 }
14417
14418 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14419 {
14420         static texture_t texture;
14421         static msurface_t surface;
14422         const msurface_t *surfacelist = &surface;
14423
14424         // fake enough texture and surface state to render this geometry
14425
14426         texture.update_lastrenderframe = -1; // regenerate this texture
14427         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14428         texture.currentskinframe = skinframe;
14429         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14430         texture.offsetmapping = OFFSETMAPPING_OFF;
14431         texture.offsetscale = 1;
14432         texture.specularscalemod = 1;
14433         texture.specularpowermod = 1;
14434
14435         surface.texture = &texture;
14436         surface.num_triangles = numtriangles;
14437         surface.num_firsttriangle = firsttriangle;
14438         surface.num_vertices = numvertices;
14439         surface.num_firstvertex = firstvertex;
14440
14441         // now render it
14442         rsurface.texture = R_GetCurrentTexture(surface.texture);
14443         rsurface.lightmaptexture = NULL;
14444         rsurface.deluxemaptexture = NULL;
14445         rsurface.uselightmaptexture = false;
14446         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14447 }
14448
14449 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)
14450 {
14451         static msurface_t surface;
14452         const msurface_t *surfacelist = &surface;
14453
14454         // fake enough texture and surface state to render this geometry
14455
14456         surface.texture = texture;
14457         surface.num_triangles = numtriangles;
14458         surface.num_firsttriangle = firsttriangle;
14459         surface.num_vertices = numvertices;
14460         surface.num_firstvertex = firstvertex;
14461
14462         // now render it
14463         rsurface.texture = R_GetCurrentTexture(surface.texture);
14464         rsurface.lightmaptexture = NULL;
14465         rsurface.deluxemaptexture = NULL;
14466         rsurface.uselightmaptexture = false;
14467         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14468 }