]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
fix two warpzone related PVS bugs
[divverent/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 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
96 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
97 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
98 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."};
99 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
100 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
101 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
102 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."};
103 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
104 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
105 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
106 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
107 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"};
108 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"};
109 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
110 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
111 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
112 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
113 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"};
114
115 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
116 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
117 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
118 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
119 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
120 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
121 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
122 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
123
124 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)"};
125 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"};
126
127 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
128 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
129 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
130 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
131 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
132
133 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
134 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
135 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
136
137 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)"};
138 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
139 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
140 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
141 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
142 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)"};
143 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)"};
144 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)"};
145 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)"};
146
147 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)"};
148 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
149 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"};
150 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
151 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
152
153 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
154 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
155 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
156 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
157
158 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
159 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
160 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
161 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
162 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
163 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
164 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
165
166 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
167 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
168 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
169 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)"};
170
171 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"};
172
173 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"};
174
175 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
176
177 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
178 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"};
179 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
180 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
181 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
182 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
183 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)"};
184
185 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
186
187 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)"};
188
189 extern cvar_t v_glslgamma;
190
191 extern qboolean v_flipped_state;
192
193 static struct r_bloomstate_s
194 {
195         qboolean enabled;
196         qboolean hdr;
197
198         int bloomwidth, bloomheight;
199
200         int screentexturewidth, screentextureheight;
201         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
202
203         int bloomtexturewidth, bloomtextureheight;
204         rtexture_t *texture_bloom;
205
206         // arrays for rendering the screen passes
207         float screentexcoord2f[8];
208         float bloomtexcoord2f[8];
209         float offsettexcoord2f[8];
210
211         r_viewport_t viewport;
212 }
213 r_bloomstate;
214
215 r_waterstate_t r_waterstate;
216
217 /// shadow volume bsp struct with automatically growing nodes buffer
218 svbsp_t r_svbsp;
219
220 rtexture_t *r_texture_blanknormalmap;
221 rtexture_t *r_texture_white;
222 rtexture_t *r_texture_grey128;
223 rtexture_t *r_texture_black;
224 rtexture_t *r_texture_notexture;
225 rtexture_t *r_texture_whitecube;
226 rtexture_t *r_texture_normalizationcube;
227 rtexture_t *r_texture_fogattenuation;
228 rtexture_t *r_texture_fogheighttexture;
229 rtexture_t *r_texture_gammaramps;
230 unsigned int r_texture_gammaramps_serial;
231 //rtexture_t *r_texture_fogintensity;
232 rtexture_t *r_texture_reflectcube;
233
234 // TODO: hash lookups?
235 typedef struct cubemapinfo_s
236 {
237         char basename[64];
238         rtexture_t *texture;
239 }
240 cubemapinfo_t;
241
242 int r_texture_numcubemaps;
243 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
244
245 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
246 unsigned int r_numqueries;
247 unsigned int r_maxqueries;
248
249 typedef struct r_qwskincache_s
250 {
251         char name[MAX_QPATH];
252         skinframe_t *skinframe;
253 }
254 r_qwskincache_t;
255
256 static r_qwskincache_t *r_qwskincache;
257 static int r_qwskincache_size;
258
259 /// vertex coordinates for a quad that covers the screen exactly
260 extern const float r_screenvertex3f[12];
261 extern const float r_d3dscreenvertex3f[12];
262 const float r_screenvertex3f[12] =
263 {
264         0, 0, 0,
265         1, 0, 0,
266         1, 1, 0,
267         0, 1, 0
268 };
269 const float r_d3dscreenvertex3f[12] =
270 {
271         0, 1, 0,
272         1, 1, 0,
273         1, 0, 0,
274         0, 0, 0
275 };
276
277 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
278 {
279         int i;
280         for (i = 0;i < verts;i++)
281         {
282                 out[0] = in[0] * r;
283                 out[1] = in[1] * g;
284                 out[2] = in[2] * b;
285                 out[3] = in[3];
286                 in += 4;
287                 out += 4;
288         }
289 }
290
291 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
292 {
293         int i;
294         for (i = 0;i < verts;i++)
295         {
296                 out[0] = r;
297                 out[1] = g;
298                 out[2] = b;
299                 out[3] = a;
300                 out += 4;
301         }
302 }
303
304 // FIXME: move this to client?
305 void FOG_clear(void)
306 {
307         if (gamemode == GAME_NEHAHRA)
308         {
309                 Cvar_Set("gl_fogenable", "0");
310                 Cvar_Set("gl_fogdensity", "0.2");
311                 Cvar_Set("gl_fogred", "0.3");
312                 Cvar_Set("gl_foggreen", "0.3");
313                 Cvar_Set("gl_fogblue", "0.3");
314         }
315         r_refdef.fog_density = 0;
316         r_refdef.fog_red = 0;
317         r_refdef.fog_green = 0;
318         r_refdef.fog_blue = 0;
319         r_refdef.fog_alpha = 1;
320         r_refdef.fog_start = 0;
321         r_refdef.fog_end = 16384;
322         r_refdef.fog_height = 1<<30;
323         r_refdef.fog_fadedepth = 128;
324         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
325 }
326
327 static void R_BuildBlankTextures(void)
328 {
329         unsigned char data[4];
330         data[2] = 128; // normal X
331         data[1] = 128; // normal Y
332         data[0] = 255; // normal Z
333         data[3] = 128; // height
334         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
335         data[0] = 255;
336         data[1] = 255;
337         data[2] = 255;
338         data[3] = 255;
339         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
340         data[0] = 128;
341         data[1] = 128;
342         data[2] = 128;
343         data[3] = 255;
344         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
345         data[0] = 0;
346         data[1] = 0;
347         data[2] = 0;
348         data[3] = 255;
349         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
350 }
351
352 static void R_BuildNoTexture(void)
353 {
354         int x, y;
355         unsigned char pix[16][16][4];
356         // this makes a light grey/dark grey checkerboard texture
357         for (y = 0;y < 16;y++)
358         {
359                 for (x = 0;x < 16;x++)
360                 {
361                         if ((y < 8) ^ (x < 8))
362                         {
363                                 pix[y][x][0] = 128;
364                                 pix[y][x][1] = 128;
365                                 pix[y][x][2] = 128;
366                                 pix[y][x][3] = 255;
367                         }
368                         else
369                         {
370                                 pix[y][x][0] = 64;
371                                 pix[y][x][1] = 64;
372                                 pix[y][x][2] = 64;
373                                 pix[y][x][3] = 255;
374                         }
375                 }
376         }
377         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
378 }
379
380 static void R_BuildWhiteCube(void)
381 {
382         unsigned char data[6*1*1*4];
383         memset(data, 255, sizeof(data));
384         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNormalizationCube(void)
388 {
389         int x, y, side;
390         vec3_t v;
391         vec_t s, t, intensity;
392 #define NORMSIZE 64
393         unsigned char *data;
394         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
395         for (side = 0;side < 6;side++)
396         {
397                 for (y = 0;y < NORMSIZE;y++)
398                 {
399                         for (x = 0;x < NORMSIZE;x++)
400                         {
401                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
402                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
403                                 switch(side)
404                                 {
405                                 default:
406                                 case 0:
407                                         v[0] = 1;
408                                         v[1] = -t;
409                                         v[2] = -s;
410                                         break;
411                                 case 1:
412                                         v[0] = -1;
413                                         v[1] = -t;
414                                         v[2] = s;
415                                         break;
416                                 case 2:
417                                         v[0] = s;
418                                         v[1] = 1;
419                                         v[2] = t;
420                                         break;
421                                 case 3:
422                                         v[0] = s;
423                                         v[1] = -1;
424                                         v[2] = -t;
425                                         break;
426                                 case 4:
427                                         v[0] = s;
428                                         v[1] = -t;
429                                         v[2] = 1;
430                                         break;
431                                 case 5:
432                                         v[0] = -s;
433                                         v[1] = -t;
434                                         v[2] = -1;
435                                         break;
436                                 }
437                                 intensity = 127.0f / sqrt(DotProduct(v, v));
438                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
439                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
440                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
441                                 data[((side*64+y)*64+x)*4+3] = 255;
442                         }
443                 }
444         }
445         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
446         Mem_Free(data);
447 }
448
449 static void R_BuildFogTexture(void)
450 {
451         int x, b;
452 #define FOGWIDTH 256
453         unsigned char data1[FOGWIDTH][4];
454         //unsigned char data2[FOGWIDTH][4];
455         double d, r, alpha;
456
457         r_refdef.fogmasktable_start = r_refdef.fog_start;
458         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
459         r_refdef.fogmasktable_range = r_refdef.fogrange;
460         r_refdef.fogmasktable_density = r_refdef.fog_density;
461
462         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
463         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
464         {
465                 d = (x * r - r_refdef.fogmasktable_start);
466                 if(developer_extra.integer)
467                         Con_DPrintf("%f ", d);
468                 d = max(0, d);
469                 if (r_fog_exp2.integer)
470                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
471                 else
472                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
473                 if(developer_extra.integer)
474                         Con_DPrintf(" : %f ", alpha);
475                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
476                 if(developer_extra.integer)
477                         Con_DPrintf(" = %f\n", alpha);
478                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
479         }
480
481         for (x = 0;x < FOGWIDTH;x++)
482         {
483                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
484                 data1[x][0] = b;
485                 data1[x][1] = b;
486                 data1[x][2] = b;
487                 data1[x][3] = 255;
488                 //data2[x][0] = 255 - b;
489                 //data2[x][1] = 255 - b;
490                 //data2[x][2] = 255 - b;
491                 //data2[x][3] = 255;
492         }
493         if (r_texture_fogattenuation)
494         {
495                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
496                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
497         }
498         else
499         {
500                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
501                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
502         }
503 }
504
505 static void R_BuildFogHeightTexture(void)
506 {
507         unsigned char *inpixels;
508         int size;
509         int x;
510         int y;
511         int j;
512         float c[4];
513         float f;
514         inpixels = NULL;
515         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
516         if (r_refdef.fogheighttexturename[0])
517                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
518         if (!inpixels)
519         {
520                 r_refdef.fog_height_tablesize = 0;
521                 if (r_texture_fogheighttexture)
522                         R_FreeTexture(r_texture_fogheighttexture);
523                 r_texture_fogheighttexture = NULL;
524                 if (r_refdef.fog_height_table2d)
525                         Mem_Free(r_refdef.fog_height_table2d);
526                 r_refdef.fog_height_table2d = NULL;
527                 if (r_refdef.fog_height_table1d)
528                         Mem_Free(r_refdef.fog_height_table1d);
529                 r_refdef.fog_height_table1d = NULL;
530                 return;
531         }
532         size = image_width;
533         r_refdef.fog_height_tablesize = size;
534         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
535         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
536         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
537         Mem_Free(inpixels);
538         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
539         // average fog color table accounting for every fog layer between a point
540         // and the camera.  (Note: attenuation is handled separately!)
541         for (y = 0;y < size;y++)
542         {
543                 for (x = 0;x < size;x++)
544                 {
545                         Vector4Clear(c);
546                         f = 0;
547                         if (x < y)
548                         {
549                                 for (j = x;j <= y;j++)
550                                 {
551                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
552                                         f++;
553                                 }
554                         }
555                         else
556                         {
557                                 for (j = x;j >= y;j--)
558                                 {
559                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
560                                         f++;
561                                 }
562                         }
563                         f = 1.0f / f;
564                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
565                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
566                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
567                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
568                 }
569         }
570         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
571 }
572
573 //=======================================================================================================================================================
574
575 static const char *builtinshaderstring =
576 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
577 "// written by Forest 'LordHavoc' Hale\n"
578 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
579 "\n"
580 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
581 "# define USEFOG\n"
582 "#endif\n"
583 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
584 "#define USELIGHTMAP\n"
585 "#endif\n"
586 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
587 "#define USEEYEVECTOR\n"
588 "#endif\n"
589 "\n"
590 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
591 "# extension GL_ARB_texture_rectangle : enable\n"
592 "#endif\n"
593 "\n"
594 "#ifdef USESHADOWMAP2D\n"
595 "# ifdef GL_EXT_gpu_shader4\n"
596 "#   extension GL_EXT_gpu_shader4 : enable\n"
597 "# endif\n"
598 "# ifdef GL_ARB_texture_gather\n"
599 "#   extension GL_ARB_texture_gather : enable\n"
600 "# else\n"
601 "#   ifdef GL_AMD_texture_texture4\n"
602 "#     extension GL_AMD_texture_texture4 : enable\n"
603 "#   endif\n"
604 "# endif\n"
605 "#endif\n"
606 "\n"
607 "#ifdef USESHADOWMAPCUBE\n"
608 "# extension GL_EXT_gpu_shader4 : enable\n"
609 "#endif\n"
610 "\n"
611 "//#ifdef USESHADOWSAMPLER\n"
612 "//# extension GL_ARB_shadow : enable\n"
613 "//#endif\n"
614 "\n"
615 "//#ifdef __GLSL_CG_DATA_TYPES\n"
616 "//# define myhalf half\n"
617 "//# define myhalf2 half2\n"
618 "//# define myhalf3 half3\n"
619 "//# define myhalf4 half4\n"
620 "//#else\n"
621 "# define myhalf float\n"
622 "# define myhalf2 vec2\n"
623 "# define myhalf3 vec3\n"
624 "# define myhalf4 vec4\n"
625 "//#endif\n"
626 "\n"
627 "#ifdef VERTEX_SHADER\n"
628 "uniform mat4 ModelViewProjectionMatrix;\n"
629 "#endif\n"
630 "\n"
631 "#ifdef MODE_DEPTH_OR_SHADOW\n"
632 "#ifdef VERTEX_SHADER\n"
633 "void main(void)\n"
634 "{\n"
635 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
636 "}\n"
637 "#endif\n"
638 "#else // !MODE_DEPTH_ORSHADOW\n"
639 "\n"
640 "\n"
641 "\n"
642 "\n"
643 "#ifdef MODE_SHOWDEPTH\n"
644 "#ifdef VERTEX_SHADER\n"
645 "void main(void)\n"
646 "{\n"
647 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
648 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
649 "}\n"
650 "#endif\n"
651 "\n"
652 "#ifdef FRAGMENT_SHADER\n"
653 "void main(void)\n"
654 "{\n"
655 "       gl_FragColor = gl_Color;\n"
656 "}\n"
657 "#endif\n"
658 "#else // !MODE_SHOWDEPTH\n"
659 "\n"
660 "\n"
661 "\n"
662 "\n"
663 "#ifdef MODE_POSTPROCESS\n"
664 "varying vec2 TexCoord1;\n"
665 "varying vec2 TexCoord2;\n"
666 "\n"
667 "#ifdef VERTEX_SHADER\n"
668 "void main(void)\n"
669 "{\n"
670 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
671 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
672 "#ifdef USEBLOOM\n"
673 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
674 "#endif\n"
675 "}\n"
676 "#endif\n"
677 "\n"
678 "#ifdef FRAGMENT_SHADER\n"
679 "uniform sampler2D Texture_First;\n"
680 "#ifdef USEBLOOM\n"
681 "uniform sampler2D Texture_Second;\n"
682 "uniform vec4 BloomColorSubtract;\n"
683 "#endif\n"
684 "#ifdef USEGAMMARAMPS\n"
685 "uniform sampler2D Texture_GammaRamps;\n"
686 "#endif\n"
687 "#ifdef USESATURATION\n"
688 "uniform float Saturation;\n"
689 "#endif\n"
690 "#ifdef USEVIEWTINT\n"
691 "uniform vec4 ViewTintColor;\n"
692 "#endif\n"
693 "//uncomment these if you want to use them:\n"
694 "uniform vec4 UserVec1;\n"
695 "uniform vec4 UserVec2;\n"
696 "// uniform vec4 UserVec3;\n"
697 "// uniform vec4 UserVec4;\n"
698 "// uniform float ClientTime;\n"
699 "uniform vec2 PixelSize;\n"
700 "void main(void)\n"
701 "{\n"
702 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
703 "#ifdef USEBLOOM\n"
704 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
705 "#endif\n"
706 "#ifdef USEVIEWTINT\n"
707 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
708 "#endif\n"
709 "\n"
710 "#ifdef USEPOSTPROCESSING\n"
711 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
712 "// 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"
713 "       float sobel = 1.0;\n"
714 "       // vec2 ts = textureSize(Texture_First, 0);\n"
715 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
716 "       vec2 px = PixelSize;\n"
717 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
718 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
719 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
720 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
721 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
722 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
723 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
724 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
725 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
726 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
727 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
728 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
729 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
730 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
731 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
732 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
733 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
734 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
735 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
736 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
737 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
738 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
739 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
740 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
741 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
742 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
743 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
744 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
745 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
746 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
747 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
748 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
749 "#endif\n"
750 "\n"
751 "#ifdef USESATURATION\n"
752 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
753 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
754 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
755 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
756 "#endif\n"
757 "\n"
758 "#ifdef USEGAMMARAMPS\n"
759 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
760 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
761 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
762 "#endif\n"
763 "}\n"
764 "#endif\n"
765 "#else // !MODE_POSTPROCESS\n"
766 "\n"
767 "\n"
768 "\n"
769 "\n"
770 "#ifdef MODE_GENERIC\n"
771 "#ifdef USEDIFFUSE\n"
772 "varying vec2 TexCoord1;\n"
773 "#endif\n"
774 "#ifdef USESPECULAR\n"
775 "varying vec2 TexCoord2;\n"
776 "#endif\n"
777 "#ifdef VERTEX_SHADER\n"
778 "void main(void)\n"
779 "{\n"
780 "       gl_FrontColor = gl_Color;\n"
781 "#ifdef USEDIFFUSE\n"
782 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
783 "#endif\n"
784 "#ifdef USESPECULAR\n"
785 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
786 "#endif\n"
787 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
788 "}\n"
789 "#endif\n"
790 "\n"
791 "#ifdef FRAGMENT_SHADER\n"
792 "#ifdef USEDIFFUSE\n"
793 "uniform sampler2D Texture_First;\n"
794 "#endif\n"
795 "#ifdef USESPECULAR\n"
796 "uniform sampler2D Texture_Second;\n"
797 "#endif\n"
798 "\n"
799 "void main(void)\n"
800 "{\n"
801 "       gl_FragColor = gl_Color;\n"
802 "#ifdef USEDIFFUSE\n"
803 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
804 "#endif\n"
805 "\n"
806 "#ifdef USESPECULAR\n"
807 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
808 "# ifdef USECOLORMAPPING\n"
809 "       gl_FragColor *= tex2;\n"
810 "# endif\n"
811 "# ifdef USEGLOW\n"
812 "       gl_FragColor += tex2;\n"
813 "# endif\n"
814 "# ifdef USEVERTEXTEXTUREBLEND\n"
815 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
816 "# endif\n"
817 "#endif\n"
818 "}\n"
819 "#endif\n"
820 "#else // !MODE_GENERIC\n"
821 "\n"
822 "\n"
823 "\n"
824 "\n"
825 "#ifdef MODE_BLOOMBLUR\n"
826 "varying TexCoord;\n"
827 "#ifdef VERTEX_SHADER\n"
828 "void main(void)\n"
829 "{\n"
830 "       gl_FrontColor = gl_Color;\n"
831 "       TexCoord = gl_MultiTexCoord0.xy;\n"
832 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
833 "}\n"
834 "#endif\n"
835 "\n"
836 "#ifdef FRAGMENT_SHADER\n"
837 "uniform sampler2D Texture_First;\n"
838 "uniform vec4 BloomBlur_Parameters;\n"
839 "\n"
840 "void main(void)\n"
841 "{\n"
842 "       int i;\n"
843 "       vec2 tc = TexCoord;\n"
844 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
845 "       tc += BloomBlur_Parameters.xy;\n"
846 "       for (i = 1;i < SAMPLES;i++)\n"
847 "       {\n"
848 "               color += texture2D(Texture_First, tc).rgb;\n"
849 "               tc += BloomBlur_Parameters.xy;\n"
850 "       }\n"
851 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
852 "}\n"
853 "#endif\n"
854 "#else // !MODE_BLOOMBLUR\n"
855 "#ifdef MODE_REFRACTION\n"
856 "varying vec2 TexCoord;\n"
857 "varying vec4 ModelViewProjectionPosition;\n"
858 "uniform mat4 TexMatrix;\n"
859 "#ifdef VERTEX_SHADER\n"
860 "\n"
861 "void main(void)\n"
862 "{\n"
863 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
864 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
865 "       ModelViewProjectionPosition = gl_Position;\n"
866 "}\n"
867 "#endif\n"
868 "\n"
869 "#ifdef FRAGMENT_SHADER\n"
870 "uniform sampler2D Texture_Normal;\n"
871 "uniform sampler2D Texture_Refraction;\n"
872 "uniform sampler2D Texture_Reflection;\n"
873 "\n"
874 "uniform vec4 DistortScaleRefractReflect;\n"
875 "uniform vec4 ScreenScaleRefractReflect;\n"
876 "uniform vec4 ScreenCenterRefractReflect;\n"
877 "uniform vec4 RefractColor;\n"
878 "uniform vec4 ReflectColor;\n"
879 "uniform float ReflectFactor;\n"
880 "uniform float ReflectOffset;\n"
881 "\n"
882 "void main(void)\n"
883 "{\n"
884 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
885 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
886 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
887 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
888 "       // FIXME temporary hack to detect the case that the reflection\n"
889 "       // gets blackened at edges due to leaving the area that contains actual\n"
890 "       // content.\n"
891 "       // Remove this 'ack once we have a better way to stop this thing from\n"
892 "       // 'appening.\n"
893 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
894 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
895 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
896 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
897 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
898 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
899 "}\n"
900 "#endif\n"
901 "#else // !MODE_REFRACTION\n"
902 "\n"
903 "\n"
904 "\n"
905 "\n"
906 "#ifdef MODE_WATER\n"
907 "varying vec2 TexCoord;\n"
908 "varying vec3 EyeVector;\n"
909 "varying vec4 ModelViewProjectionPosition;\n"
910 "#ifdef VERTEX_SHADER\n"
911 "uniform vec3 EyePosition;\n"
912 "uniform mat4 TexMatrix;\n"
913 "\n"
914 "void main(void)\n"
915 "{\n"
916 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
917 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
918 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
919 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
920 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
921 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
922 "       ModelViewProjectionPosition = gl_Position;\n"
923 "}\n"
924 "#endif\n"
925 "\n"
926 "#ifdef FRAGMENT_SHADER\n"
927 "uniform sampler2D Texture_Normal;\n"
928 "uniform sampler2D Texture_Refraction;\n"
929 "uniform sampler2D Texture_Reflection;\n"
930 "\n"
931 "uniform vec4 DistortScaleRefractReflect;\n"
932 "uniform vec4 ScreenScaleRefractReflect;\n"
933 "uniform vec4 ScreenCenterRefractReflect;\n"
934 "uniform vec4 RefractColor;\n"
935 "uniform vec4 ReflectColor;\n"
936 "uniform float ReflectFactor;\n"
937 "uniform float ReflectOffset;\n"
938 "\n"
939 "void main(void)\n"
940 "{\n"
941 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
942 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
943 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
944 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
945 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
946 "       // FIXME temporary hack to detect the case that the reflection\n"
947 "       // gets blackened at edges due to leaving the area that contains actual\n"
948 "       // content.\n"
949 "       // Remove this 'ack once we have a better way to stop this thing from\n"
950 "       // 'appening.\n"
951 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
952 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
953 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
954 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
955 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
956 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
957 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
958 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
959 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
960 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
961 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
962 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
963 "}\n"
964 "#endif\n"
965 "#else // !MODE_WATER\n"
966 "\n"
967 "\n"
968 "\n"
969 "\n"
970 "// common definitions between vertex shader and fragment shader:\n"
971 "\n"
972 "varying vec2 TexCoord;\n"
973 "#ifdef USEVERTEXTEXTUREBLEND\n"
974 "varying vec2 TexCoord2;\n"
975 "#endif\n"
976 "#ifdef USELIGHTMAP\n"
977 "varying vec2 TexCoordLightmap;\n"
978 "#endif\n"
979 "\n"
980 "#ifdef MODE_LIGHTSOURCE\n"
981 "varying vec3 CubeVector;\n"
982 "#endif\n"
983 "\n"
984 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
985 "varying vec3 LightVector;\n"
986 "#endif\n"
987 "\n"
988 "#ifdef USEEYEVECTOR\n"
989 "varying vec3 EyeVector;\n"
990 "#endif\n"
991 "#ifdef USEFOG\n"
992 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
993 "#endif\n"
994 "\n"
995 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
996 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
997 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
998 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
999 "#endif\n"
1000 "\n"
1001 "#ifdef USEREFLECTION\n"
1002 "varying vec4 ModelViewProjectionPosition;\n"
1003 "#endif\n"
1004 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1005 "uniform vec3 LightPosition;\n"
1006 "varying vec4 ModelViewPosition;\n"
1007 "#endif\n"
1008 "\n"
1009 "#ifdef MODE_LIGHTSOURCE\n"
1010 "uniform vec3 LightPosition;\n"
1011 "#endif\n"
1012 "uniform vec3 EyePosition;\n"
1013 "#ifdef MODE_LIGHTDIRECTION\n"
1014 "uniform vec3 LightDir;\n"
1015 "#endif\n"
1016 "uniform vec4 FogPlane;\n"
1017 "\n"
1018 "#ifdef USESHADOWMAPORTHO\n"
1019 "varying vec3 ShadowMapTC;\n"
1020 "#endif\n"
1021 "\n"
1022 "\n"
1023 "\n"
1024 "\n"
1025 "\n"
1026 "// 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"
1027 "\n"
1028 "// fragment shader specific:\n"
1029 "#ifdef FRAGMENT_SHADER\n"
1030 "\n"
1031 "uniform sampler2D Texture_Normal;\n"
1032 "uniform sampler2D Texture_Color;\n"
1033 "uniform sampler2D Texture_Gloss;\n"
1034 "#ifdef USEGLOW\n"
1035 "uniform sampler2D Texture_Glow;\n"
1036 "#endif\n"
1037 "#ifdef USEVERTEXTEXTUREBLEND\n"
1038 "uniform sampler2D Texture_SecondaryNormal;\n"
1039 "uniform sampler2D Texture_SecondaryColor;\n"
1040 "uniform sampler2D Texture_SecondaryGloss;\n"
1041 "#ifdef USEGLOW\n"
1042 "uniform sampler2D Texture_SecondaryGlow;\n"
1043 "#endif\n"
1044 "#endif\n"
1045 "#ifdef USECOLORMAPPING\n"
1046 "uniform sampler2D Texture_Pants;\n"
1047 "uniform sampler2D Texture_Shirt;\n"
1048 "#endif\n"
1049 "#ifdef USEFOG\n"
1050 "#ifdef USEFOGHEIGHTTEXTURE\n"
1051 "uniform sampler2D Texture_FogHeightTexture;\n"
1052 "#endif\n"
1053 "uniform sampler2D Texture_FogMask;\n"
1054 "#endif\n"
1055 "#ifdef USELIGHTMAP\n"
1056 "uniform sampler2D Texture_Lightmap;\n"
1057 "#endif\n"
1058 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1059 "uniform sampler2D Texture_Deluxemap;\n"
1060 "#endif\n"
1061 "#ifdef USEREFLECTION\n"
1062 "uniform sampler2D Texture_Reflection;\n"
1063 "#endif\n"
1064 "\n"
1065 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1066 "uniform sampler2D Texture_ScreenDepth;\n"
1067 "uniform sampler2D Texture_ScreenNormalMap;\n"
1068 "#endif\n"
1069 "#ifdef USEDEFERREDLIGHTMAP\n"
1070 "uniform sampler2D Texture_ScreenDiffuse;\n"
1071 "uniform sampler2D Texture_ScreenSpecular;\n"
1072 "#endif\n"
1073 "\n"
1074 "uniform myhalf3 Color_Pants;\n"
1075 "uniform myhalf3 Color_Shirt;\n"
1076 "uniform myhalf3 FogColor;\n"
1077 "\n"
1078 "#ifdef USEFOG\n"
1079 "uniform float FogRangeRecip;\n"
1080 "uniform float FogPlaneViewDist;\n"
1081 "uniform float FogHeightFade;\n"
1082 "vec3 FogVertex(vec3 surfacecolor)\n"
1083 "{\n"
1084 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1085 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1086 "       float fogfrac;\n"
1087 "#ifdef USEFOGHEIGHTTEXTURE\n"
1088 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1089 "       fogfrac = fogheightpixel.a;\n"
1090 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1091 "#else\n"
1092 "# ifdef USEFOGOUTSIDE\n"
1093 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1094 "# else\n"
1095 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1096 "# endif\n"
1097 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1098 "#endif\n"
1099 "}\n"
1100 "#endif\n"
1101 "\n"
1102 "#ifdef USEOFFSETMAPPING\n"
1103 "uniform float OffsetMapping_Scale;\n"
1104 "vec2 OffsetMapping(vec2 TexCoord)\n"
1105 "{\n"
1106 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1107 "       // 14 sample relief mapping: linear search and then binary search\n"
1108 "       // this basically steps forward a small amount repeatedly until it finds\n"
1109 "       // itself inside solid, then jitters forward and back using decreasing\n"
1110 "       // amounts to find the impact\n"
1111 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1112 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1113 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1114 "       vec3 RT = vec3(TexCoord, 1);\n"
1115 "       OffsetVector *= 0.1;\n"
1116 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1117 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1118 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1119 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1120 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1121 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1122 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1123 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1124 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1125 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1126 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1127 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1128 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1129 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1130 "       return RT.xy;\n"
1131 "#else\n"
1132 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1133 "       // this basically moves forward the full distance, and then backs up based\n"
1134 "       // on height of samples\n"
1135 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1136 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1137 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1138 "       TexCoord += OffsetVector;\n"
1139 "       OffsetVector *= 0.333;\n"
1140 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1141 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1142 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1143 "       return TexCoord;\n"
1144 "#endif\n"
1145 "}\n"
1146 "#endif // USEOFFSETMAPPING\n"
1147 "\n"
1148 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1149 "uniform sampler2D Texture_Attenuation;\n"
1150 "uniform samplerCube Texture_Cube;\n"
1151 "#endif\n"
1152 "\n"
1153 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1154 "\n"
1155 "#ifdef USESHADOWMAPRECT\n"
1156 "# ifdef USESHADOWSAMPLER\n"
1157 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1158 "# else\n"
1159 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1160 "# endif\n"
1161 "#endif\n"
1162 "\n"
1163 "#ifdef USESHADOWMAP2D\n"
1164 "# ifdef USESHADOWSAMPLER\n"
1165 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1166 "# else\n"
1167 "uniform sampler2D Texture_ShadowMap2D;\n"
1168 "# endif\n"
1169 "#endif\n"
1170 "\n"
1171 "#ifdef USESHADOWMAPVSDCT\n"
1172 "uniform samplerCube Texture_CubeProjection;\n"
1173 "#endif\n"
1174 "\n"
1175 "#ifdef USESHADOWMAPCUBE\n"
1176 "# ifdef USESHADOWSAMPLER\n"
1177 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1178 "# else\n"
1179 "uniform samplerCube Texture_ShadowMapCube;\n"
1180 "# endif\n"
1181 "#endif\n"
1182 "\n"
1183 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1184 "uniform vec2 ShadowMap_TextureScale;\n"
1185 "uniform vec4 ShadowMap_Parameters;\n"
1186 "#endif\n"
1187 "\n"
1188 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1189 "# ifdef USESHADOWMAPORTHO\n"
1190 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1191 "# else\n"
1192 "#  ifdef USESHADOWMAPVSDCT\n"
1193 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1194 "{\n"
1195 "       vec3 adir = abs(dir);\n"
1196 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1197 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1198 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1199 "}\n"
1200 "#  else\n"
1201 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1202 "{\n"
1203 "       vec3 adir = abs(dir);\n"
1204 "       float ma = adir.z;\n"
1205 "       vec4 proj = vec4(dir, 2.5);\n"
1206 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1207 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1208 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1209 "       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"
1210 "}\n"
1211 "#  endif\n"
1212 "# endif\n"
1213 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1214 "\n"
1215 "#ifdef USESHADOWMAPCUBE\n"
1216 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1217 "{\n"
1218 "       vec3 adir = abs(dir);\n"
1219 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1220 "}\n"
1221 "#endif\n"
1222 "\n"
1223 "# ifdef USESHADOWMAPRECT\n"
1224 "float ShadowMapCompare(vec3 dir)\n"
1225 "{\n"
1226 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1227 "       float f;\n"
1228 "#  ifdef USESHADOWSAMPLER\n"
1229 "\n"
1230 "#    ifdef USESHADOWMAPPCF\n"
1231 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1232 "       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"
1233 "#    else\n"
1234 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1235 "#    endif\n"
1236 "\n"
1237 "#  else\n"
1238 "\n"
1239 "#    ifdef USESHADOWMAPPCF\n"
1240 "#      if USESHADOWMAPPCF > 1\n"
1241 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1242 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1243 "       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"
1244 "       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"
1245 "       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"
1246 "       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"
1247 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1248 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1249 "#      else\n"
1250 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1251 "       vec2 offset = fract(shadowmaptc.xy);\n"
1252 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1253 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1254 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1255 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1256 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1257 "#      endif\n"
1258 "#    else\n"
1259 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1260 "#    endif\n"
1261 "\n"
1262 "#  endif\n"
1263 "#  ifdef USESHADOWMAPORTHO\n"
1264 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1265 "#  else\n"
1266 "       return f;\n"
1267 "#  endif\n"
1268 "}\n"
1269 "# endif\n"
1270 "\n"
1271 "# ifdef USESHADOWMAP2D\n"
1272 "float ShadowMapCompare(vec3 dir)\n"
1273 "{\n"
1274 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1275 "       float f;\n"
1276 "\n"
1277 "#  ifdef USESHADOWSAMPLER\n"
1278 "#    ifdef USESHADOWMAPPCF\n"
1279 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1280 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1281 "       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"
1282 "#    else\n"
1283 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1284 "#    endif\n"
1285 "#  else\n"
1286 "#    ifdef USESHADOWMAPPCF\n"
1287 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1288 "#      ifdef GL_ARB_texture_gather\n"
1289 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1290 "#      else\n"
1291 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1292 "#      endif\n"
1293 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1294 "#      if USESHADOWMAPPCF > 1\n"
1295 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1296 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1297 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1298 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1299 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1300 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1301 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1302 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1303 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1304 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1305 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1306 "       locols.yz += group2.ab;\n"
1307 "       hicols.yz += group8.rg;\n"
1308 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1309 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1310 "                               mix(locols, hicols, offset.y);\n"
1311 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1312 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1313 "       f = dot(cols, vec4(1.0/25.0));\n"
1314 "#      else\n"
1315 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1316 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1317 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1318 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1319 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1320 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1321 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1322 "#      endif\n"
1323 "#     else\n"
1324 "#      ifdef GL_EXT_gpu_shader4\n"
1325 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1326 "#      else\n"
1327 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1328 "#      endif\n"
1329 "#      if USESHADOWMAPPCF > 1\n"
1330 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1331 "       center *= ShadowMap_TextureScale;\n"
1332 "       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"
1333 "       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"
1334 "       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"
1335 "       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"
1336 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1337 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1338 "#      else\n"
1339 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1340 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1341 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1342 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1343 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1344 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1345 "#      endif\n"
1346 "#     endif\n"
1347 "#    else\n"
1348 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1349 "#    endif\n"
1350 "#  endif\n"
1351 "#  ifdef USESHADOWMAPORTHO\n"
1352 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1353 "#  else\n"
1354 "       return f;\n"
1355 "#  endif\n"
1356 "}\n"
1357 "# endif\n"
1358 "\n"
1359 "# ifdef USESHADOWMAPCUBE\n"
1360 "float ShadowMapCompare(vec3 dir)\n"
1361 "{\n"
1362 "       // apply depth texture cubemap as light filter\n"
1363 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1364 "       float f;\n"
1365 "#  ifdef USESHADOWSAMPLER\n"
1366 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1367 "#  else\n"
1368 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1369 "#  endif\n"
1370 "       return f;\n"
1371 "}\n"
1372 "# endif\n"
1373 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1374 "#endif // FRAGMENT_SHADER\n"
1375 "\n"
1376 "\n"
1377 "\n"
1378 "\n"
1379 "#ifdef MODE_DEFERREDGEOMETRY\n"
1380 "#ifdef VERTEX_SHADER\n"
1381 "uniform mat4 TexMatrix;\n"
1382 "#ifdef USEVERTEXTEXTUREBLEND\n"
1383 "uniform mat4 BackgroundTexMatrix;\n"
1384 "#endif\n"
1385 "uniform mat4 ModelViewMatrix;\n"
1386 "void main(void)\n"
1387 "{\n"
1388 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 "       gl_FrontColor = gl_Color;\n"
1391 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1392 "#endif\n"
1393 "\n"
1394 "       // transform unnormalized eye direction into tangent space\n"
1395 "#ifdef USEOFFSETMAPPING\n"
1396 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1397 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1398 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1399 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1400 "#endif\n"
1401 "\n"
1402 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1403 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1404 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1405 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1406 "}\n"
1407 "#endif // VERTEX_SHADER\n"
1408 "\n"
1409 "#ifdef FRAGMENT_SHADER\n"
1410 "void main(void)\n"
1411 "{\n"
1412 "#ifdef USEOFFSETMAPPING\n"
1413 "       // apply offsetmapping\n"
1414 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1415 "#define TexCoord TexCoordOffset\n"
1416 "#endif\n"
1417 "\n"
1418 "#ifdef USEALPHAKILL\n"
1419 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1420 "               discard;\n"
1421 "#endif\n"
1422 "\n"
1423 "#ifdef USEVERTEXTEXTUREBLEND\n"
1424 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1425 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1426 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1427 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1428 "#endif\n"
1429 "\n"
1430 "#ifdef USEVERTEXTEXTUREBLEND\n"
1431 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1432 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1433 "#else\n"
1434 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1435 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1436 "#endif\n"
1437 "\n"
1438 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1439 "}\n"
1440 "#endif // FRAGMENT_SHADER\n"
1441 "#else // !MODE_DEFERREDGEOMETRY\n"
1442 "\n"
1443 "\n"
1444 "\n"
1445 "\n"
1446 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1447 "#ifdef VERTEX_SHADER\n"
1448 "uniform mat4 ModelViewMatrix;\n"
1449 "void main(void)\n"
1450 "{\n"
1451 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1452 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1453 "}\n"
1454 "#endif // VERTEX_SHADER\n"
1455 "\n"
1456 "#ifdef FRAGMENT_SHADER\n"
1457 "uniform mat4 ViewToLight;\n"
1458 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1459 "uniform vec2 ScreenToDepth;\n"
1460 "uniform myhalf3 DeferredColor_Ambient;\n"
1461 "uniform myhalf3 DeferredColor_Diffuse;\n"
1462 "#ifdef USESPECULAR\n"
1463 "uniform myhalf3 DeferredColor_Specular;\n"
1464 "uniform myhalf SpecularPower;\n"
1465 "#endif\n"
1466 "uniform myhalf2 PixelToScreenTexCoord;\n"
1467 "void main(void)\n"
1468 "{\n"
1469 "       // calculate viewspace pixel position\n"
1470 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1471 "       vec3 position;\n"
1472 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1473 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1474 "       // decode viewspace pixel normal\n"
1475 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1476 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1477 "       // surfacenormal = pixel normal in viewspace\n"
1478 "       // LightVector = pixel to light in viewspace\n"
1479 "       // CubeVector = position in lightspace\n"
1480 "       // eyevector = pixel to view in viewspace\n"
1481 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1482 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1483 "#ifdef USEDIFFUSE\n"
1484 "       // calculate diffuse shading\n"
1485 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1486 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1487 "#endif\n"
1488 "#ifdef USESPECULAR\n"
1489 "       // calculate directional shading\n"
1490 "       vec3 eyevector = position * -1.0;\n"
1491 "#  ifdef USEEXACTSPECULARMATH\n"
1492 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1493 "#  else\n"
1494 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1495 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1496 "#  endif\n"
1497 "#endif\n"
1498 "\n"
1499 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1500 "       fade *= ShadowMapCompare(CubeVector);\n"
1501 "#endif\n"
1502 "\n"
1503 "#ifdef USEDIFFUSE\n"
1504 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1505 "#else\n"
1506 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1507 "#endif\n"
1508 "#ifdef USESPECULAR\n"
1509 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1510 "#else\n"
1511 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1512 "#endif\n"
1513 "\n"
1514 "# ifdef USECUBEFILTER\n"
1515 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1516 "       gl_FragData[0].rgb *= cubecolor;\n"
1517 "       gl_FragData[1].rgb *= cubecolor;\n"
1518 "# endif\n"
1519 "}\n"
1520 "#endif // FRAGMENT_SHADER\n"
1521 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1522 "\n"
1523 "\n"
1524 "\n"
1525 "\n"
1526 "#ifdef VERTEX_SHADER\n"
1527 "uniform mat4 TexMatrix;\n"
1528 "#ifdef USEVERTEXTEXTUREBLEND\n"
1529 "uniform mat4 BackgroundTexMatrix;\n"
1530 "#endif\n"
1531 "#ifdef MODE_LIGHTSOURCE\n"
1532 "uniform mat4 ModelToLight;\n"
1533 "#endif\n"
1534 "#ifdef USESHADOWMAPORTHO\n"
1535 "uniform mat4 ShadowMapMatrix;\n"
1536 "#endif\n"
1537 "void main(void)\n"
1538 "{\n"
1539 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1540 "       gl_FrontColor = gl_Color;\n"
1541 "#endif\n"
1542 "       // copy the surface texcoord\n"
1543 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1544 "#ifdef USEVERTEXTEXTUREBLEND\n"
1545 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1546 "#endif\n"
1547 "#ifdef USELIGHTMAP\n"
1548 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1549 "#endif\n"
1550 "\n"
1551 "#ifdef MODE_LIGHTSOURCE\n"
1552 "       // transform vertex position into light attenuation/cubemap space\n"
1553 "       // (-1 to +1 across the light box)\n"
1554 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1555 "\n"
1556 "# ifdef USEDIFFUSE\n"
1557 "       // transform unnormalized light direction into tangent space\n"
1558 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1559 "       //  normalize it per pixel)\n"
1560 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1561 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1562 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1563 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1564 "# endif\n"
1565 "#endif\n"
1566 "\n"
1567 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1568 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1569 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1570 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1571 "#endif\n"
1572 "\n"
1573 "       // transform unnormalized eye direction into tangent space\n"
1574 "#ifdef USEEYEVECTOR\n"
1575 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1576 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1577 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1578 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1579 "#endif\n"
1580 "\n"
1581 "#ifdef USEFOG\n"
1582 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1583 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1584 "#endif\n"
1585 "\n"
1586 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1587 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1588 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1589 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1590 "#endif\n"
1591 "\n"
1592 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1593 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1594 "\n"
1595 "#ifdef USESHADOWMAPORTHO\n"
1596 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1597 "#endif\n"
1598 "\n"
1599 "#ifdef USEREFLECTION\n"
1600 "       ModelViewProjectionPosition = gl_Position;\n"
1601 "#endif\n"
1602 "}\n"
1603 "#endif // VERTEX_SHADER\n"
1604 "\n"
1605 "\n"
1606 "\n"
1607 "\n"
1608 "#ifdef FRAGMENT_SHADER\n"
1609 "#ifdef USEDEFERREDLIGHTMAP\n"
1610 "uniform myhalf2 PixelToScreenTexCoord;\n"
1611 "uniform myhalf3 DeferredMod_Diffuse;\n"
1612 "uniform myhalf3 DeferredMod_Specular;\n"
1613 "#endif\n"
1614 "uniform myhalf3 Color_Ambient;\n"
1615 "uniform myhalf3 Color_Diffuse;\n"
1616 "uniform myhalf3 Color_Specular;\n"
1617 "uniform myhalf SpecularPower;\n"
1618 "#ifdef USEGLOW\n"
1619 "uniform myhalf3 Color_Glow;\n"
1620 "#endif\n"
1621 "uniform myhalf Alpha;\n"
1622 "#ifdef USEREFLECTION\n"
1623 "uniform vec4 DistortScaleRefractReflect;\n"
1624 "uniform vec4 ScreenScaleRefractReflect;\n"
1625 "uniform vec4 ScreenCenterRefractReflect;\n"
1626 "uniform myhalf4 ReflectColor;\n"
1627 "#endif\n"
1628 "#ifdef USEREFLECTCUBE\n"
1629 "uniform mat4 ModelToReflectCube;\n"
1630 "uniform sampler2D Texture_ReflectMask;\n"
1631 "uniform samplerCube Texture_ReflectCube;\n"
1632 "#endif\n"
1633 "#ifdef MODE_LIGHTDIRECTION\n"
1634 "uniform myhalf3 LightColor;\n"
1635 "#endif\n"
1636 "#ifdef MODE_LIGHTSOURCE\n"
1637 "uniform myhalf3 LightColor;\n"
1638 "#endif\n"
1639 "void main(void)\n"
1640 "{\n"
1641 "#ifdef USEOFFSETMAPPING\n"
1642 "       // apply offsetmapping\n"
1643 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1644 "#define TexCoord TexCoordOffset\n"
1645 "#endif\n"
1646 "\n"
1647 "       // combine the diffuse textures (base, pants, shirt)\n"
1648 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1649 "#ifdef USEALPHAKILL\n"
1650 "       if (color.a < 0.5)\n"
1651 "               discard;\n"
1652 "#endif\n"
1653 "       color.a *= Alpha;\n"
1654 "#ifdef USECOLORMAPPING\n"
1655 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1656 "#endif\n"
1657 "#ifdef USEVERTEXTEXTUREBLEND\n"
1658 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1659 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1660 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1661 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1662 "       color.a = 1.0;\n"
1663 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1664 "#endif\n"
1665 "\n"
1666 "       // get the surface normal\n"
1667 "#ifdef USEVERTEXTEXTUREBLEND\n"
1668 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1669 "#else\n"
1670 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1671 "#endif\n"
1672 "\n"
1673 "       // get the material colors\n"
1674 "       myhalf3 diffusetex = color.rgb;\n"
1675 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1676 "# ifdef USEVERTEXTEXTUREBLEND\n"
1677 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1678 "# else\n"
1679 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1680 "# endif\n"
1681 "#endif\n"
1682 "\n"
1683 "#ifdef USEREFLECTCUBE\n"
1684 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1685 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1686 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1687 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1688 "#endif\n"
1689 "\n"
1690 "\n"
1691 "\n"
1692 "\n"
1693 "#ifdef MODE_LIGHTSOURCE\n"
1694 "       // light source\n"
1695 "#ifdef USEDIFFUSE\n"
1696 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1697 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1698 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1699 "#ifdef USESPECULAR\n"
1700 "#ifdef USEEXACTSPECULARMATH\n"
1701 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1702 "#else\n"
1703 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1704 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1705 "#endif\n"
1706 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1707 "#endif\n"
1708 "#else\n"
1709 "       color.rgb = diffusetex * Color_Ambient;\n"
1710 "#endif\n"
1711 "       color.rgb *= LightColor;\n"
1712 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1713 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1714 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1715 "#endif\n"
1716 "# ifdef USECUBEFILTER\n"
1717 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1718 "# endif\n"
1719 "#endif // MODE_LIGHTSOURCE\n"
1720 "\n"
1721 "\n"
1722 "\n"
1723 "\n"
1724 "#ifdef MODE_LIGHTDIRECTION\n"
1725 "#define SHADING\n"
1726 "#ifdef USEDIFFUSE\n"
1727 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1728 "#endif\n"
1729 "#define lightcolor LightColor\n"
1730 "#endif // MODE_LIGHTDIRECTION\n"
1731 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1732 "#define SHADING\n"
1733 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1734 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1735 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1736 "       // convert modelspace light vector to tangentspace\n"
1737 "       myhalf3 lightnormal;\n"
1738 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1739 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1740 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1741 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1742 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1743 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1744 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1745 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1746 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1747 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1748 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1749 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1750 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1751 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1752 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1753 "#define SHADING\n"
1754 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1755 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1756 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1757 "#endif\n"
1758 "\n"
1759 "\n"
1760 "\n"
1761 "\n"
1762 "#ifdef MODE_LIGHTMAP\n"
1763 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1764 "#endif // MODE_LIGHTMAP\n"
1765 "#ifdef MODE_VERTEXCOLOR\n"
1766 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1767 "#endif // MODE_VERTEXCOLOR\n"
1768 "#ifdef MODE_FLATCOLOR\n"
1769 "       color.rgb = diffusetex * Color_Ambient;\n"
1770 "#endif // MODE_FLATCOLOR\n"
1771 "\n"
1772 "\n"
1773 "\n"
1774 "\n"
1775 "#ifdef SHADING\n"
1776 "# ifdef USEDIFFUSE\n"
1777 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1778 "#  ifdef USESPECULAR\n"
1779 "#   ifdef USEEXACTSPECULARMATH\n"
1780 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1781 "#   else\n"
1782 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1783 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1784 "#   endif\n"
1785 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1786 "#  else\n"
1787 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1788 "#  endif\n"
1789 "# else\n"
1790 "       color.rgb = diffusetex * Color_Ambient;\n"
1791 "# endif\n"
1792 "#endif\n"
1793 "\n"
1794 "#ifdef USESHADOWMAPORTHO\n"
1795 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1796 "#endif\n"
1797 "\n"
1798 "#ifdef USEDEFERREDLIGHTMAP\n"
1799 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1800 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1801 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1802 "#endif\n"
1803 "\n"
1804 "#ifdef USEGLOW\n"
1805 "#ifdef USEVERTEXTEXTUREBLEND\n"
1806 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1807 "#else\n"
1808 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1809 "#endif\n"
1810 "#endif\n"
1811 "\n"
1812 "#ifdef USEFOG\n"
1813 "       color.rgb = FogVertex(color.rgb);\n"
1814 "#endif\n"
1815 "\n"
1816 "       // 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"
1817 "#ifdef USEREFLECTION\n"
1818 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1819 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1820 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1821 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1822 "       // FIXME temporary hack to detect the case that the reflection\n"
1823 "       // gets blackened at edges due to leaving the area that contains actual\n"
1824 "       // content.\n"
1825 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1826 "       // 'appening.\n"
1827 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1828 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1829 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1830 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1831 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1832 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1833 "#endif\n"
1834 "\n"
1835 "       gl_FragColor = vec4(color);\n"
1836 "}\n"
1837 "#endif // FRAGMENT_SHADER\n"
1838 "\n"
1839 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1840 "#endif // !MODE_DEFERREDGEOMETRY\n"
1841 "#endif // !MODE_WATER\n"
1842 "#endif // !MODE_REFRACTION\n"
1843 "#endif // !MODE_BLOOMBLUR\n"
1844 "#endif // !MODE_GENERIC\n"
1845 "#endif // !MODE_POSTPROCESS\n"
1846 "#endif // !MODE_SHOWDEPTH\n"
1847 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1848 ;
1849
1850 /*
1851 =========================================================================================================================================================
1852
1853
1854
1855 =========================================================================================================================================================
1856
1857
1858
1859 =========================================================================================================================================================
1860
1861
1862
1863 =========================================================================================================================================================
1864
1865
1866
1867 =========================================================================================================================================================
1868
1869
1870
1871 =========================================================================================================================================================
1872
1873
1874
1875 =========================================================================================================================================================
1876 */
1877
1878 const char *builtincgshaderstring =
1879 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1880 "// written by Forest 'LordHavoc' Hale\n"
1881 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1882 "\n"
1883 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1884 "#if defined(USEREFLECTION)\n"
1885 "#undef USESHADOWMAPORTHO\n"
1886 "#endif\n"
1887 "\n"
1888 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1889 "# define USEFOG\n"
1890 "#endif\n"
1891 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1892 "#define USELIGHTMAP\n"
1893 "#endif\n"
1894 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1895 "#define USEEYEVECTOR\n"
1896 "#endif\n"
1897 "\n"
1898 "#ifdef FRAGMENT_SHADER\n"
1899 "#ifdef HLSL\n"
1900 "//#undef USESHADOWMAPPCF\n"
1901 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1902 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1903 "#else\n"
1904 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1905 "#endif\n"
1906 "#endif\n"
1907 "\n"
1908 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1909 "#ifdef VERTEX_SHADER\n"
1910 "void main\n"
1911 "(\n"
1912 "float4 gl_Vertex : POSITION,\n"
1913 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1914 "out float4 gl_Position : POSITION,\n"
1915 "out float Depth : TEXCOORD0\n"
1916 ")\n"
1917 "{\n"
1918 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1919 "       Depth = gl_Position.z;\n"
1920 "}\n"
1921 "#endif\n"
1922 "\n"
1923 "#ifdef FRAGMENT_SHADER\n"
1924 "void main\n"
1925 "(\n"
1926 "float Depth : TEXCOORD0,\n"
1927 "out float4 gl_FragColor : COLOR\n"
1928 ")\n"
1929 "{\n"
1930 "//     float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1931 "       float3 temp = float3(Depth,Depth*256.0,Depth*65536.0);\n"
1932 "       temp.yz -= floor(temp.yz);\n"
1933 "       gl_FragColor = float4(temp,0);\n"
1934 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1935 "}\n"
1936 "#endif\n"
1937 "#else // !MODE_DEPTH_ORSHADOW\n"
1938 "\n"
1939 "\n"
1940 "\n"
1941 "\n"
1942 "#ifdef MODE_SHOWDEPTH\n"
1943 "#ifdef VERTEX_SHADER\n"
1944 "void main\n"
1945 "(\n"
1946 "float4 gl_Vertex : POSITION,\n"
1947 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1948 "out float4 gl_Position : POSITION,\n"
1949 "out float4 gl_FrontColor : COLOR0\n"
1950 ")\n"
1951 "{\n"
1952 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1953 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1954 "}\n"
1955 "#endif\n"
1956 "\n"
1957 "#ifdef FRAGMENT_SHADER\n"
1958 "void main\n"
1959 "(\n"
1960 "float4 gl_FrontColor : COLOR0,\n"
1961 "out float4 gl_FragColor : COLOR\n"
1962 ")\n"
1963 "{\n"
1964 "       gl_FragColor = gl_FrontColor;\n"
1965 "}\n"
1966 "#endif\n"
1967 "#else // !MODE_SHOWDEPTH\n"
1968 "\n"
1969 "\n"
1970 "\n"
1971 "\n"
1972 "#ifdef MODE_POSTPROCESS\n"
1973 "\n"
1974 "#ifdef VERTEX_SHADER\n"
1975 "void main\n"
1976 "(\n"
1977 "float4 gl_Vertex : POSITION,\n"
1978 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1979 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1980 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1981 "out float4 gl_Position : POSITION,\n"
1982 "out float2 TexCoord1 : TEXCOORD0,\n"
1983 "out float2 TexCoord2 : TEXCOORD1\n"
1984 ")\n"
1985 "{\n"
1986 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1987 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1988 "#ifdef USEBLOOM\n"
1989 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1990 "#endif\n"
1991 "}\n"
1992 "#endif\n"
1993 "\n"
1994 "#ifdef FRAGMENT_SHADER\n"
1995 "void main\n"
1996 "(\n"
1997 "float2 TexCoord1 : TEXCOORD0,\n"
1998 "float2 TexCoord2 : TEXCOORD1,\n"
1999 "uniform sampler Texture_First : register(s0),\n"
2000 "#ifdef USEBLOOM\n"
2001 "uniform sampler Texture_Second : register(s1),\n"
2002 "#endif\n"
2003 "#ifdef USEGAMMARAMPS\n"
2004 "uniform sampler Texture_GammaRamps : register(s2),\n"
2005 "#endif\n"
2006 "#ifdef USESATURATION\n"
2007 "uniform float Saturation : register(c30),\n"
2008 "#endif\n"
2009 "#ifdef USEVIEWTINT\n"
2010 "uniform float4 ViewTintColor : register(c41),\n"
2011 "#endif\n"
2012 "uniform float4 UserVec1 : register(c37),\n"
2013 "uniform float4 UserVec2 : register(c38),\n"
2014 "uniform float4 UserVec3 : register(c39),\n"
2015 "uniform float4 UserVec4 : register(c40),\n"
2016 "uniform float ClientTime : register(c2),\n"
2017 "uniform float2 PixelSize : register(c25),\n"
2018 "uniform float4 BloomColorSubtract : register(c43),\n"
2019 "out float4 gl_FragColor : COLOR\n"
2020 ")\n"
2021 "{\n"
2022 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2023 "#ifdef USEBLOOM\n"
2024 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2025 "#endif\n"
2026 "#ifdef USEVIEWTINT\n"
2027 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2028 "#endif\n"
2029 "\n"
2030 "#ifdef USEPOSTPROCESSING\n"
2031 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2032 "// 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"
2033 "       float sobel = 1.0;\n"
2034 "       // float2 ts = textureSize(Texture_First, 0);\n"
2035 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2036 "       float2 px = PixelSize;\n"
2037 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2038 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2039 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2040 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2041 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2042 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2043 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2044 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2045 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2046 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2047 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2048 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2049 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2050 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2051 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2052 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2053 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2054 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2055 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2056 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2057 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2058 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2059 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2060 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2061 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2062 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2063 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2064 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2065 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2066 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2067 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2068 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2069 "#endif\n"
2070 "\n"
2071 "#ifdef USESATURATION\n"
2072 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2073 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2074 "       //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2075 "       gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2076 "#endif\n"
2077 "\n"
2078 "#ifdef USEGAMMARAMPS\n"
2079 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2080 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2081 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2082 "#endif\n"
2083 "}\n"
2084 "#endif\n"
2085 "#else // !MODE_POSTPROCESS\n"
2086 "\n"
2087 "\n"
2088 "\n"
2089 "\n"
2090 "#ifdef MODE_GENERIC\n"
2091 "#ifdef VERTEX_SHADER\n"
2092 "void main\n"
2093 "(\n"
2094 "float4 gl_Vertex : POSITION,\n"
2095 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2096 "float4 gl_Color : COLOR0,\n"
2097 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2098 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2099 "out float4 gl_Position : POSITION,\n"
2100 "out float4 gl_FrontColor : COLOR,\n"
2101 "out float2 TexCoord1 : TEXCOORD0,\n"
2102 "out float2 TexCoord2 : TEXCOORD1\n"
2103 ")\n"
2104 "{\n"
2105 "#ifdef HLSL\n"
2106 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2107 "#else\n"
2108 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2109 "#endif\n"
2110 "#ifdef USEDIFFUSE\n"
2111 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2112 "#endif\n"
2113 "#ifdef USESPECULAR\n"
2114 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2115 "#endif\n"
2116 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2117 "}\n"
2118 "#endif\n"
2119 "\n"
2120 "#ifdef FRAGMENT_SHADER\n"
2121 "\n"
2122 "void main\n"
2123 "(\n"
2124 "float4 gl_FrontColor : COLOR0,\n"
2125 "float2 TexCoord1 : TEXCOORD0,\n"
2126 "float2 TexCoord2 : TEXCOORD1,\n"
2127 "#ifdef USEDIFFUSE\n"
2128 "uniform sampler Texture_First : register(s0),\n"
2129 "#endif\n"
2130 "#ifdef USESPECULAR\n"
2131 "uniform sampler Texture_Second : register(s1),\n"
2132 "#endif\n"
2133 "out float4 gl_FragColor : COLOR\n"
2134 ")\n"
2135 "{\n"
2136 "       gl_FragColor = gl_FrontColor;\n"
2137 "#ifdef USEDIFFUSE\n"
2138 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2139 "#endif\n"
2140 "\n"
2141 "#ifdef USESPECULAR\n"
2142 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2143 "# ifdef USECOLORMAPPING\n"
2144 "       gl_FragColor *= tex2;\n"
2145 "# endif\n"
2146 "# ifdef USEGLOW\n"
2147 "       gl_FragColor += tex2;\n"
2148 "# endif\n"
2149 "# ifdef USEVERTEXTEXTUREBLEND\n"
2150 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2151 "# endif\n"
2152 "#endif\n"
2153 "}\n"
2154 "#endif\n"
2155 "#else // !MODE_GENERIC\n"
2156 "\n"
2157 "\n"
2158 "\n"
2159 "\n"
2160 "#ifdef MODE_BLOOMBLUR\n"
2161 "#ifdef VERTEX_SHADER\n"
2162 "void main\n"
2163 "(\n"
2164 "float4 gl_Vertex : POSITION,\n"
2165 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2166 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2167 "out float4 gl_Position : POSITION,\n"
2168 "out float2 TexCoord : TEXCOORD0\n"
2169 ")\n"
2170 "{\n"
2171 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2172 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2173 "}\n"
2174 "#endif\n"
2175 "\n"
2176 "#ifdef FRAGMENT_SHADER\n"
2177 "\n"
2178 "void main\n"
2179 "(\n"
2180 "float2 TexCoord : TEXCOORD0,\n"
2181 "uniform sampler Texture_First : register(s0),\n"
2182 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2183 "out float4 gl_FragColor : COLOR\n"
2184 ")\n"
2185 "{\n"
2186 "       int i;\n"
2187 "       float2 tc = TexCoord;\n"
2188 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2189 "       tc += BloomBlur_Parameters.xy;\n"
2190 "       for (i = 1;i < SAMPLES;i++)\n"
2191 "       {\n"
2192 "               color += tex2D(Texture_First, tc).rgb;\n"
2193 "               tc += BloomBlur_Parameters.xy;\n"
2194 "       }\n"
2195 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2196 "}\n"
2197 "#endif\n"
2198 "#else // !MODE_BLOOMBLUR\n"
2199 "#ifdef MODE_REFRACTION\n"
2200 "#ifdef VERTEX_SHADER\n"
2201 "void main\n"
2202 "(\n"
2203 "float4 gl_Vertex : POSITION,\n"
2204 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2205 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2206 "uniform float4x4 TexMatrix : register(c0),\n"
2207 "uniform float3 EyePosition : register(c24),\n"
2208 "out float4 gl_Position : POSITION,\n"
2209 "out float2 TexCoord : TEXCOORD0,\n"
2210 "out float3 EyeVector : TEXCOORD1,\n"
2211 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2212 ")\n"
2213 "{\n"
2214 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2215 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2216 "       ModelViewProjectionPosition = gl_Position;\n"
2217 "}\n"
2218 "#endif\n"
2219 "\n"
2220 "#ifdef FRAGMENT_SHADER\n"
2221 "void main\n"
2222 "(\n"
2223 "float2 TexCoord : TEXCOORD0,\n"
2224 "float3 EyeVector : TEXCOORD1,\n"
2225 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2226 "uniform sampler Texture_Normal : register(s0),\n"
2227 "uniform sampler Texture_Refraction : register(s3),\n"
2228 "uniform sampler Texture_Reflection : register(s7),\n"
2229 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2230 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2231 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2232 "uniform float4 RefractColor : register(c29),\n"
2233 "out float4 gl_FragColor : COLOR\n"
2234 ")\n"
2235 "{\n"
2236 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2237 "       //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"
2238 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2239 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2240 "       // FIXME temporary hack to detect the case that the reflection\n"
2241 "       // gets blackened at edges due to leaving the area that contains actual\n"
2242 "       // content.\n"
2243 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2244 "       // 'appening.\n"
2245 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2246 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2247 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2248 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2249 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2250 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2251 "}\n"
2252 "#endif\n"
2253 "#else // !MODE_REFRACTION\n"
2254 "\n"
2255 "\n"
2256 "\n"
2257 "\n"
2258 "#ifdef MODE_WATER\n"
2259 "#ifdef VERTEX_SHADER\n"
2260 "\n"
2261 "void main\n"
2262 "(\n"
2263 "float4 gl_Vertex : POSITION,\n"
2264 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2265 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2266 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2267 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2268 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2269 "uniform float4x4 TexMatrix : register(c0),\n"
2270 "uniform float3 EyePosition : register(c24),\n"
2271 "out float4 gl_Position : POSITION,\n"
2272 "out float2 TexCoord : TEXCOORD0,\n"
2273 "out float3 EyeVector : TEXCOORD1,\n"
2274 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2275 ")\n"
2276 "{\n"
2277 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2278 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2279 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2280 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2281 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2282 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2283 "       ModelViewProjectionPosition = gl_Position;\n"
2284 "}\n"
2285 "#endif\n"
2286 "\n"
2287 "#ifdef FRAGMENT_SHADER\n"
2288 "void main\n"
2289 "(\n"
2290 "float2 TexCoord : TEXCOORD0,\n"
2291 "float3 EyeVector : TEXCOORD1,\n"
2292 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2293 "uniform sampler Texture_Normal : register(s0),\n"
2294 "uniform sampler Texture_Refraction : register(s3),\n"
2295 "uniform sampler Texture_Reflection : register(s7),\n"
2296 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2297 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2298 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2299 "uniform float4 RefractColor : register(c29),\n"
2300 "uniform float4 ReflectColor : register(c26),\n"
2301 "uniform float ReflectFactor : register(c27),\n"
2302 "uniform float ReflectOffset : register(c28),\n"
2303 "out float4 gl_FragColor : COLOR\n"
2304 ")\n"
2305 "{\n"
2306 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2307 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2308 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2309 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2310 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2311 "       // FIXME temporary hack to detect the case that the reflection\n"
2312 "       // gets blackened at edges due to leaving the area that contains actual\n"
2313 "       // content.\n"
2314 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2315 "       // 'appening.\n"
2316 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2317 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2318 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2319 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2320 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2321 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2322 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2323 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2324 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2325 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2326 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2327 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2328 "}\n"
2329 "#endif\n"
2330 "#else // !MODE_WATER\n"
2331 "\n"
2332 "\n"
2333 "\n"
2334 "\n"
2335 "// 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"
2336 "\n"
2337 "// fragment shader specific:\n"
2338 "#ifdef FRAGMENT_SHADER\n"
2339 "\n"
2340 "#ifdef USEFOG\n"
2341 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2342 "{\n"
2343 "       float fogfrac;\n"
2344 "#ifdef USEFOGHEIGHTTEXTURE\n"
2345 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2346 "       fogfrac = fogheightpixel.a;\n"
2347 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2348 "#else\n"
2349 "# ifdef USEFOGOUTSIDE\n"
2350 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2351 "# else\n"
2352 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2353 "# endif\n"
2354 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2355 "#endif\n"
2356 "}\n"
2357 "#endif\n"
2358 "\n"
2359 "#ifdef USEOFFSETMAPPING\n"
2360 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2361 "{\n"
2362 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2363 "       // 14 sample relief mapping: linear search and then binary search\n"
2364 "       // this basically steps forward a small amount repeatedly until it finds\n"
2365 "       // itself inside solid, then jitters forward and back using decreasing\n"
2366 "       // amounts to find the impact\n"
2367 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2368 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2369 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2370 "       float3 RT = float3(TexCoord, 1);\n"
2371 "       OffsetVector *= 0.1;\n"
2372 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2373 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2374 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2375 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2376 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2377 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2378 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2379 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2380 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2381 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2382 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2383 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2384 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2385 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2386 "       return RT.xy;\n"
2387 "#else\n"
2388 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2389 "       // this basically moves forward the full distance, and then backs up based\n"
2390 "       // on height of samples\n"
2391 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2392 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2393 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2394 "       TexCoord += OffsetVector;\n"
2395 "       OffsetVector *= 0.333;\n"
2396 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2397 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2398 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2399 "       return TexCoord;\n"
2400 "#endif\n"
2401 "}\n"
2402 "#endif // USEOFFSETMAPPING\n"
2403 "\n"
2404 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2405 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2406 "# ifdef USESHADOWMAPORTHO\n"
2407 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2408 "# else\n"
2409 "#  ifdef USESHADOWMAPVSDCT\n"
2410 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2411 "{\n"
2412 "       float3 adir = abs(dir);\n"
2413 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2414 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2415 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2416 "}\n"
2417 "#  else\n"
2418 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2419 "{\n"
2420 "       float3 adir = abs(dir);\n"
2421 "       float ma = adir.z;\n"
2422 "       float4 proj = float4(dir, 2.5);\n"
2423 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2424 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2425 "#ifdef HLSL\n"
2426 "       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"
2427 "#else\n"
2428 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2429 "       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"
2430 "#endif\n"
2431 "}\n"
2432 "#  endif\n"
2433 "# endif\n"
2434 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2435 "\n"
2436 "#ifdef USESHADOWMAPCUBE\n"
2437 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2438 "{\n"
2439 "       float3 adir = abs(dir);\n"
2440 "       return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2441 "}\n"
2442 "#endif\n"
2443 "\n"
2444 "# ifdef USESHADOWMAPRECT\n"
2445 "#ifdef USESHADOWMAPVSDCT\n"
2446 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2447 "#else\n"
2448 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2449 "#endif\n"
2450 "{\n"
2451 "#ifdef USESHADOWMAPVSDCT\n"
2452 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2453 "#else\n"
2454 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2455 "#endif\n"
2456 "       float f;\n"
2457 "#  ifdef USESHADOWSAMPLER\n"
2458 "\n"
2459 "#    ifdef USESHADOWMAPPCF\n"
2460 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2461 "       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"
2462 "#    else\n"
2463 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2464 "#    endif\n"
2465 "\n"
2466 "#  else\n"
2467 "\n"
2468 "#    ifdef USESHADOWMAPPCF\n"
2469 "#      if USESHADOWMAPPCF > 1\n"
2470 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2471 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2472 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2473 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2474 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2475 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2476 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2477 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2478 "#      else\n"
2479 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2480 "       float2 offset = frac(shadowmaptc.xy);\n"
2481 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2482 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2483 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2484 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2485 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2486 "#      endif\n"
2487 "#    else\n"
2488 "       f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2489 "#    endif\n"
2490 "\n"
2491 "#  endif\n"
2492 "#  ifdef USESHADOWMAPORTHO\n"
2493 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2494 "#  else\n"
2495 "       return f;\n"
2496 "#  endif\n"
2497 "}\n"
2498 "# endif\n"
2499 "\n"
2500 "# ifdef USESHADOWMAP2D\n"
2501 "#ifdef USESHADOWMAPVSDCT\n"
2502 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2503 "#else\n"
2504 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2505 "#endif\n"
2506 "{\n"
2507 "#ifdef USESHADOWMAPVSDCT\n"
2508 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2509 "#else\n"
2510 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2511 "#endif\n"
2512 "       float f;\n"
2513 "\n"
2514 "#  ifdef USESHADOWSAMPLER\n"
2515 "#    ifdef USESHADOWMAPPCF\n"
2516 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2517 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2518 "       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"
2519 "#    else\n"
2520 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2521 "#    endif\n"
2522 "#  else\n"
2523 "#    ifdef USESHADOWMAPPCF\n"
2524 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2525 "#      ifdef GL_ARB_texture_gather\n"
2526 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2527 "#      else\n"
2528 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2529 "#      endif\n"
2530 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2531 "#      if USESHADOWMAPPCF > 1\n"
2532 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2533 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2534 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2535 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2536 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2537 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2538 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2539 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2540 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2541 "       float4 locols = float4(group1.ab, group3.ab);\n"
2542 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2543 "       locols.yz += group2.ab;\n"
2544 "       hicols.yz += group8.rg;\n"
2545 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2546 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2547 "                               lerp(locols, hicols, offset.y);\n"
2548 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2549 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2550 "       f = dot(cols, float4(1.0/25.0));\n"
2551 "#      else\n"
2552 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2553 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2554 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2555 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2556 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2557 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2558 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2559 "#      endif\n"
2560 "#     else\n"
2561 "#      ifdef GL_EXT_gpu_shader4\n"
2562 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2563 "#      else\n"
2564 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2565 "#      endif\n"
2566 "#      if USESHADOWMAPPCF > 1\n"
2567 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2568 "       center *= ShadowMap_TextureScale;\n"
2569 "       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"
2570 "       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"
2571 "       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"
2572 "       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"
2573 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2574 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2575 "#      else\n"
2576 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2577 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2578 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2579 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2580 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2581 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2582 "#      endif\n"
2583 "#     endif\n"
2584 "#    else\n"
2585 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2586 "#    endif\n"
2587 "#  endif\n"
2588 "#  ifdef USESHADOWMAPORTHO\n"
2589 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2590 "#  else\n"
2591 "       return f;\n"
2592 "#  endif\n"
2593 "}\n"
2594 "# endif\n"
2595 "\n"
2596 "# ifdef USESHADOWMAPCUBE\n"
2597 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2598 "{\n"
2599 "       // apply depth texture cubemap as light filter\n"
2600 "       float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2601 "       float f;\n"
2602 "#  ifdef USESHADOWSAMPLER\n"
2603 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2604 "#  else\n"
2605 "       f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2606 "#  endif\n"
2607 "       return f;\n"
2608 "}\n"
2609 "# endif\n"
2610 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2611 "#endif // FRAGMENT_SHADER\n"
2612 "\n"
2613 "\n"
2614 "\n"
2615 "\n"
2616 "#ifdef MODE_DEFERREDGEOMETRY\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 "#ifdef USEVERTEXTEXTUREBLEND\n"
2623 "float4 gl_Color : COLOR0,\n"
2624 "#endif\n"
2625 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2626 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2627 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2628 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2629 "uniform float4x4 TexMatrix : register(c0),\n"
2630 "#ifdef USEVERTEXTEXTUREBLEND\n"
2631 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2632 "#endif\n"
2633 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2634 "#ifdef USEOFFSETMAPPING\n"
2635 "uniform float3 EyePosition : register(c24),\n"
2636 "#endif\n"
2637 "out float4 gl_Position : POSITION,\n"
2638 "out float4 gl_FrontColor : COLOR,\n"
2639 "out float4 TexCoordBoth : TEXCOORD0,\n"
2640 "#ifdef USEOFFSETMAPPING\n"
2641 "out float3 EyeVector : TEXCOORD2,\n"
2642 "#endif\n"
2643 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2644 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2645 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2646 ")\n"
2647 "{\n"
2648 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2649 "#ifdef USEVERTEXTEXTUREBLEND\n"
2650 "#ifdef HLSL\n"
2651 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2652 "#else\n"
2653 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2654 "#endif\n"
2655 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2656 "#endif\n"
2657 "\n"
2658 "       // transform unnormalized eye direction into tangent space\n"
2659 "#ifdef USEOFFSETMAPPING\n"
2660 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2661 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2662 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2663 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2664 "#endif\n"
2665 "\n"
2666 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2667 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2668 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2669 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2670 "}\n"
2671 "#endif // VERTEX_SHADER\n"
2672 "\n"
2673 "#ifdef FRAGMENT_SHADER\n"
2674 "void main\n"
2675 "(\n"
2676 "float4 TexCoordBoth : TEXCOORD0,\n"
2677 "float3 EyeVector : TEXCOORD2,\n"
2678 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2679 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2680 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2681 "uniform sampler Texture_Normal : register(s0),\n"
2682 "#ifdef USEALPHAKILL\n"
2683 "uniform sampler Texture_Color : register(s1),\n"
2684 "#endif\n"
2685 "uniform sampler Texture_Gloss : register(s2),\n"
2686 "#ifdef USEVERTEXTEXTUREBLEND\n"
2687 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2688 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2689 "#endif\n"
2690 "#ifdef USEOFFSETMAPPING\n"
2691 "uniform float OffsetMapping_Scale : register(c24),\n"
2692 "#endif\n"
2693 "uniform half SpecularPower : register(c36),\n"
2694 "out float4 gl_FragColor : COLOR\n"
2695 ")\n"
2696 "{\n"
2697 "       float2 TexCoord = TexCoordBoth.xy;\n"
2698 "#ifdef USEOFFSETMAPPING\n"
2699 "       // apply offsetmapping\n"
2700 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2701 "#define TexCoord TexCoordOffset\n"
2702 "#endif\n"
2703 "\n"
2704 "#ifdef USEALPHAKILL\n"
2705 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2706 "               discard;\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef USEVERTEXTEXTUREBLEND\n"
2710 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2711 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2712 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2713 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2714 "#endif\n"
2715 "\n"
2716 "#ifdef USEVERTEXTEXTUREBLEND\n"
2717 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2718 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2719 "#else\n"
2720 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2721 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2722 "#endif\n"
2723 "\n"
2724 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2725 "}\n"
2726 "#endif // FRAGMENT_SHADER\n"
2727 "#else // !MODE_DEFERREDGEOMETRY\n"
2728 "\n"
2729 "\n"
2730 "\n"
2731 "\n"
2732 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2733 "#ifdef VERTEX_SHADER\n"
2734 "void main\n"
2735 "(\n"
2736 "float4 gl_Vertex : POSITION,\n"
2737 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2738 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2739 "out float4 gl_Position : POSITION,\n"
2740 "out float4 ModelViewPosition : TEXCOORD0\n"
2741 ")\n"
2742 "{\n"
2743 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2744 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2745 "}\n"
2746 "#endif // VERTEX_SHADER\n"
2747 "\n"
2748 "#ifdef FRAGMENT_SHADER\n"
2749 "void main\n"
2750 "(\n"
2751 "#ifdef HLSL\n"
2752 "float2 Pixel : VPOS,\n"
2753 "#else\n"
2754 "float2 Pixel : WPOS,\n"
2755 "#endif\n"
2756 "float4 ModelViewPosition : TEXCOORD0,\n"
2757 "uniform float4x4 ViewToLight : register(c44),\n"
2758 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2759 "uniform float3 LightPosition : register(c23),\n"
2760 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2761 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2762 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2763 "#ifdef USESPECULAR\n"
2764 "uniform half3 DeferredColor_Specular : register(c11),\n"
2765 "uniform half SpecularPower : register(c36),\n"
2766 "#endif\n"
2767 "uniform sampler Texture_Attenuation : register(s9),\n"
2768 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2769 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2770 "\n"
2771 "#ifdef USECUBEFILTER\n"
2772 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2773 "#endif\n"
2774 "\n"
2775 "#ifdef USESHADOWMAPRECT\n"
2776 "# ifdef USESHADOWSAMPLER\n"
2777 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
2778 "# else\n"
2779 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
2780 "# endif\n"
2781 "#endif\n"
2782 "\n"
2783 "#ifdef USESHADOWMAP2D\n"
2784 "# ifdef USESHADOWSAMPLER\n"
2785 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2786 "# else\n"
2787 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2788 "# endif\n"
2789 "#endif\n"
2790 "\n"
2791 "#ifdef USESHADOWMAPVSDCT\n"
2792 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2793 "#endif\n"
2794 "\n"
2795 "#ifdef USESHADOWMAPCUBE\n"
2796 "# ifdef USESHADOWSAMPLER\n"
2797 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
2798 "# else\n"
2799 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
2800 "# endif\n"
2801 "#endif\n"
2802 "\n"
2803 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2804 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2805 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2806 "#endif\n"
2807 "\n"
2808 "out float4 gl_FragData0 : COLOR0,\n"
2809 "out float4 gl_FragData1 : COLOR1\n"
2810 ")\n"
2811 "{\n"
2812 "       // calculate viewspace pixel position\n"
2813 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2814 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2815 "       float3 position;\n"
2816 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2817 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2818 "       // decode viewspace pixel normal\n"
2819 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2820 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2821 "       // surfacenormal = pixel normal in viewspace\n"
2822 "       // LightVector = pixel to light in viewspace\n"
2823 "       // CubeVector = position in lightspace\n"
2824 "       // eyevector = pixel to view in viewspace\n"
2825 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2826 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2827 "#ifdef USEDIFFUSE\n"
2828 "       // calculate diffuse shading\n"
2829 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2830 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2831 "#endif\n"
2832 "#ifdef USESPECULAR\n"
2833 "       // calculate directional shading\n"
2834 "       float3 eyevector = position * -1.0;\n"
2835 "#  ifdef USEEXACTSPECULARMATH\n"
2836 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2837 "#  else\n"
2838 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2839 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2840 "#  endif\n"
2841 "#endif\n"
2842 "\n"
2843 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2844 "       fade *= ShadowMapCompare(CubeVector,\n"
2845 "# if defined(USESHADOWMAP2D)\n"
2846 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2847 "# endif\n"
2848 "# if defined(USESHADOWMAPRECT)\n"
2849 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2850 "# endif\n"
2851 "# if defined(USESHADOWMAPCUBE)\n"
2852 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2853 "# endif\n"
2854 "\n"
2855 "#ifdef USESHADOWMAPVSDCT\n"
2856 ", Texture_CubeProjection\n"
2857 "#endif\n"
2858 "       );\n"
2859 "#endif\n"
2860 "\n"
2861 "#ifdef USEDIFFUSE\n"
2862 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2863 "#else\n"
2864 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2865 "#endif\n"
2866 "#ifdef USESPECULAR\n"
2867 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2868 "#else\n"
2869 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2870 "#endif\n"
2871 "\n"
2872 "# ifdef USECUBEFILTER\n"
2873 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2874 "       gl_FragData0.rgb *= cubecolor;\n"
2875 "       gl_FragData1.rgb *= cubecolor;\n"
2876 "# endif\n"
2877 "}\n"
2878 "#endif // FRAGMENT_SHADER\n"
2879 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2880 "\n"
2881 "\n"
2882 "\n"
2883 "\n"
2884 "#ifdef VERTEX_SHADER\n"
2885 "void main\n"
2886 "(\n"
2887 "float4 gl_Vertex : POSITION,\n"
2888 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2889 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2890 "float4 gl_Color : COLOR0,\n"
2891 "#endif\n"
2892 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2893 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2894 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2895 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2896 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2897 "\n"
2898 "uniform float3 EyePosition : register(c24),\n"
2899 "uniform float4x4 TexMatrix : register(c0),\n"
2900 "#ifdef USEVERTEXTEXTUREBLEND\n"
2901 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2902 "#endif\n"
2903 "#ifdef MODE_LIGHTSOURCE\n"
2904 "uniform float4x4 ModelToLight : register(c20),\n"
2905 "#endif\n"
2906 "#ifdef MODE_LIGHTSOURCE\n"
2907 "uniform float3 LightPosition : register(c27),\n"
2908 "#endif\n"
2909 "#ifdef MODE_LIGHTDIRECTION\n"
2910 "uniform float3 LightDir : register(c26),\n"
2911 "#endif\n"
2912 "uniform float4 FogPlane : register(c25),\n"
2913 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2914 "uniform float3 LightPosition : register(c27),\n"
2915 "#endif\n"
2916 "#ifdef USESHADOWMAPORTHO\n"
2917 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2918 "#endif\n"
2919 "\n"
2920 "out float4 gl_FrontColor : COLOR,\n"
2921 "out float4 TexCoordBoth : TEXCOORD0,\n"
2922 "#ifdef USELIGHTMAP\n"
2923 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2924 "#endif\n"
2925 "#ifdef USEEYEVECTOR\n"
2926 "out float3 EyeVector : TEXCOORD2,\n"
2927 "#endif\n"
2928 "#ifdef USEREFLECTION\n"
2929 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2930 "#endif\n"
2931 "#ifdef USEFOG\n"
2932 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2933 "#endif\n"
2934 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2935 "out float3 LightVector : TEXCOORD1,\n"
2936 "#endif\n"
2937 "#ifdef MODE_LIGHTSOURCE\n"
2938 "out float3 CubeVector : TEXCOORD3,\n"
2939 "#endif\n"
2940 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2941 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2942 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2943 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2944 "#endif\n"
2945 "#ifdef USESHADOWMAPORTHO\n"
2946 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2947 "#endif\n"
2948 "out float4 gl_Position : POSITION\n"
2949 ")\n"
2950 "{\n"
2951 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2952 "#ifdef HLSL\n"
2953 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2954 "#else\n"
2955 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2956 "#endif\n"
2957 "#endif\n"
2958 "       // copy the surface texcoord\n"
2959 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2960 "#ifdef USEVERTEXTEXTUREBLEND\n"
2961 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2962 "#endif\n"
2963 "#ifdef USELIGHTMAP\n"
2964 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2965 "#endif\n"
2966 "\n"
2967 "#ifdef MODE_LIGHTSOURCE\n"
2968 "       // transform vertex position into light attenuation/cubemap space\n"
2969 "       // (-1 to +1 across the light box)\n"
2970 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2971 "\n"
2972 "# ifdef USEDIFFUSE\n"
2973 "       // transform unnormalized light direction into tangent space\n"
2974 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2975 "       //  normalize it per pixel)\n"
2976 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2977 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2978 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2979 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2980 "# endif\n"
2981 "#endif\n"
2982 "\n"
2983 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2984 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2985 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2986 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2987 "#endif\n"
2988 "\n"
2989 "       // transform unnormalized eye direction into tangent space\n"
2990 "#ifdef USEEYEVECTOR\n"
2991 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2992 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2993 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2994 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2995 "#endif\n"
2996 "\n"
2997 "#ifdef USEFOG\n"
2998 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2999 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
3000 "#endif\n"
3001 "\n"
3002 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3003 "       VectorS = gl_MultiTexCoord1.xyz;\n"
3004 "       VectorT = gl_MultiTexCoord2.xyz;\n"
3005 "       VectorR = gl_MultiTexCoord3.xyz;\n"
3006 "#endif\n"
3007 "\n"
3008 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
3009 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
3010 "\n"
3011 "#ifdef USESHADOWMAPORTHO\n"
3012 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
3013 "#endif\n"
3014 "\n"
3015 "#ifdef USEREFLECTION\n"
3016 "       ModelViewProjectionPosition = gl_Position;\n"
3017 "#endif\n"
3018 "}\n"
3019 "#endif // VERTEX_SHADER\n"
3020 "\n"
3021 "\n"
3022 "\n"
3023 "\n"
3024 "#ifdef FRAGMENT_SHADER\n"
3025 "void main\n"
3026 "(\n"
3027 "#ifdef USEDEFERREDLIGHTMAP\n"
3028 "#ifdef HLSL\n"
3029 "float2 Pixel : VPOS,\n"
3030 "#else\n"
3031 "float2 Pixel : WPOS,\n"
3032 "#endif\n"
3033 "#endif\n"
3034 "float4 gl_FrontColor : COLOR,\n"
3035 "float4 TexCoordBoth : TEXCOORD0,\n"
3036 "#ifdef USELIGHTMAP\n"
3037 "float2 TexCoordLightmap : TEXCOORD1,\n"
3038 "#endif\n"
3039 "#ifdef USEEYEVECTOR\n"
3040 "float3 EyeVector : TEXCOORD2,\n"
3041 "#endif\n"
3042 "#ifdef USEREFLECTION\n"
3043 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
3044 "#endif\n"
3045 "#ifdef USEFOG\n"
3046 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
3047 "#endif\n"
3048 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
3049 "float3 LightVector : TEXCOORD1,\n"
3050 "#endif\n"
3051 "#ifdef MODE_LIGHTSOURCE\n"
3052 "float3 CubeVector : TEXCOORD3,\n"
3053 "#endif\n"
3054 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3055 "float4 ModelViewPosition : TEXCOORD0,\n"
3056 "#endif\n"
3057 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
3058 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
3059 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
3060 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
3061 "#endif\n"
3062 "#ifdef USESHADOWMAPORTHO\n"
3063 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
3064 "#endif\n"
3065 "\n"
3066 "uniform sampler Texture_Normal : register(s0),\n"
3067 "uniform sampler Texture_Color : register(s1),\n"
3068 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3069 "uniform sampler Texture_Gloss : register(s2),\n"
3070 "#endif\n"
3071 "#ifdef USEGLOW\n"
3072 "uniform sampler Texture_Glow : register(s3),\n"
3073 "#endif\n"
3074 "#ifdef USEVERTEXTEXTUREBLEND\n"
3075 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
3076 "uniform sampler Texture_SecondaryColor : register(s5),\n"
3077 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3078 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3079 "#endif\n"
3080 "#ifdef USEGLOW\n"
3081 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3082 "#endif\n"
3083 "#endif\n"
3084 "#ifdef USECOLORMAPPING\n"
3085 "uniform sampler Texture_Pants : register(s4),\n"
3086 "uniform sampler Texture_Shirt : register(s7),\n"
3087 "#endif\n"
3088 "#ifdef USEFOG\n"
3089 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3090 "uniform sampler Texture_FogMask : register(s8),\n"
3091 "#endif\n"
3092 "#ifdef USELIGHTMAP\n"
3093 "uniform sampler Texture_Lightmap : register(s9),\n"
3094 "#endif\n"
3095 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3096 "uniform sampler Texture_Deluxemap : register(s10),\n"
3097 "#endif\n"
3098 "#ifdef USEREFLECTION\n"
3099 "uniform sampler Texture_Reflection : register(s7),\n"
3100 "#endif\n"
3101 "\n"
3102 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3103 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3104 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3105 "#endif\n"
3106 "#ifdef USEDEFERREDLIGHTMAP\n"
3107 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3108 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3109 "#endif\n"
3110 "\n"
3111 "#ifdef USECOLORMAPPING\n"
3112 "uniform half3 Color_Pants : register(c7),\n"
3113 "uniform half3 Color_Shirt : register(c8),\n"
3114 "#endif\n"
3115 "#ifdef USEFOG\n"
3116 "uniform float3 FogColor : register(c16),\n"
3117 "uniform float FogRangeRecip : register(c20),\n"
3118 "uniform float FogPlaneViewDist : register(c19),\n"
3119 "uniform float FogHeightFade : register(c17),\n"
3120 "#endif\n"
3121 "\n"
3122 "#ifdef USEOFFSETMAPPING\n"
3123 "uniform float OffsetMapping_Scale : register(c24),\n"
3124 "#endif\n"
3125 "\n"
3126 "#ifdef USEDEFERREDLIGHTMAP\n"
3127 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3128 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3129 "uniform half3 DeferredMod_Specular : register(c13),\n"
3130 "#endif\n"
3131 "uniform half3 Color_Ambient : register(c3),\n"
3132 "uniform half3 Color_Diffuse : register(c4),\n"
3133 "uniform half3 Color_Specular : register(c5),\n"
3134 "uniform half SpecularPower : register(c36),\n"
3135 "#ifdef USEGLOW\n"
3136 "uniform half3 Color_Glow : register(c6),\n"
3137 "#endif\n"
3138 "uniform half Alpha : register(c0),\n"
3139 "#ifdef USEREFLECTION\n"
3140 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3141 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3142 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3143 "uniform half4 ReflectColor : register(c26),\n"
3144 "#endif\n"
3145 "#ifdef USEREFLECTCUBE\n"
3146 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3147 "uniform sampler Texture_ReflectMask : register(s5),\n"
3148 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3149 "#endif\n"
3150 "#ifdef MODE_LIGHTDIRECTION\n"
3151 "uniform half3 LightColor : register(c21),\n"
3152 "#endif\n"
3153 "#ifdef MODE_LIGHTSOURCE\n"
3154 "uniform half3 LightColor : register(c21),\n"
3155 "#endif\n"
3156 "\n"
3157 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3158 "uniform sampler Texture_Attenuation : register(s9),\n"
3159 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3160 "#endif\n"
3161 "\n"
3162 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3163 "\n"
3164 "#ifdef USESHADOWMAPRECT\n"
3165 "# ifdef USESHADOWSAMPLER\n"
3166 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
3167 "# else\n"
3168 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
3169 "# endif\n"
3170 "#endif\n"
3171 "\n"
3172 "#ifdef USESHADOWMAP2D\n"
3173 "# ifdef USESHADOWSAMPLER\n"
3174 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3175 "# else\n"
3176 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3177 "# endif\n"
3178 "#endif\n"
3179 "\n"
3180 "#ifdef USESHADOWMAPVSDCT\n"
3181 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3182 "#endif\n"
3183 "\n"
3184 "#ifdef USESHADOWMAPCUBE\n"
3185 "# ifdef USESHADOWSAMPLER\n"
3186 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
3187 "# else\n"
3188 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
3189 "# endif\n"
3190 "#endif\n"
3191 "\n"
3192 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3193 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3194 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3195 "#endif\n"
3196 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3197 "\n"
3198 "out float4 gl_FragColor : COLOR\n"
3199 ")\n"
3200 "{\n"
3201 "       float2 TexCoord = TexCoordBoth.xy;\n"
3202 "#ifdef USEVERTEXTEXTUREBLEND\n"
3203 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3204 "#endif\n"
3205 "#ifdef USEOFFSETMAPPING\n"
3206 "       // apply offsetmapping\n"
3207 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3208 "#define TexCoord TexCoordOffset\n"
3209 "#endif\n"
3210 "\n"
3211 "       // combine the diffuse textures (base, pants, shirt)\n"
3212 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3213 "#ifdef USEALPHAKILL\n"
3214 "       if (color.a < 0.5)\n"
3215 "               discard;\n"
3216 "#endif\n"
3217 "       color.a *= Alpha;\n"
3218 "#ifdef USECOLORMAPPING\n"
3219 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3220 "#endif\n"
3221 "#ifdef USEVERTEXTEXTUREBLEND\n"
3222 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3223 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3224 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3225 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3226 "       color.a = 1.0;\n"
3227 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3228 "#endif\n"
3229 "\n"
3230 "       // get the surface normal\n"
3231 "#ifdef USEVERTEXTEXTUREBLEND\n"
3232 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3233 "#else\n"
3234 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3235 "#endif\n"
3236 "\n"
3237 "       // get the material colors\n"
3238 "       half3 diffusetex = color.rgb;\n"
3239 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3240 "# ifdef USEVERTEXTEXTUREBLEND\n"
3241 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3242 "# else\n"
3243 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3244 "# endif\n"
3245 "#endif\n"
3246 "\n"
3247 "#ifdef USEREFLECTCUBE\n"
3248 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3249 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3250 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3251 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3252 "#endif\n"
3253 "\n"
3254 "\n"
3255 "\n"
3256 "\n"
3257 "#ifdef MODE_LIGHTSOURCE\n"
3258 "       // light source\n"
3259 "#ifdef USEDIFFUSE\n"
3260 "       half3 lightnormal = half3(normalize(LightVector));\n"
3261 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3262 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3263 "#ifdef USESPECULAR\n"
3264 "#ifdef USEEXACTSPECULARMATH\n"
3265 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3266 "#else\n"
3267 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3268 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3269 "#endif\n"
3270 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3271 "#endif\n"
3272 "#else\n"
3273 "       color.rgb = diffusetex * Color_Ambient;\n"
3274 "#endif\n"
3275 "       color.rgb *= LightColor;\n"
3276 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3277 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3278 "       color.rgb *= half(ShadowMapCompare(CubeVector,\n"
3279 "# if defined(USESHADOWMAP2D)\n"
3280 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3281 "# endif\n"
3282 "# if defined(USESHADOWMAPRECT)\n"
3283 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3284 "# endif\n"
3285 "# if defined(USESHADOWMAPCUBE)\n"
3286 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3287 "# endif\n"
3288 "\n"
3289 "#ifdef USESHADOWMAPVSDCT\n"
3290 ", Texture_CubeProjection\n"
3291 "#endif\n"
3292 "       ));\n"
3293 "\n"
3294 "#endif\n"
3295 "# ifdef USECUBEFILTER\n"
3296 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3297 "# endif\n"
3298 "\n"
3299 "#ifdef USESHADOWMAP2D\n"
3300 "#ifdef USESHADOWMAPVSDCT\n"
3301 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3302 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale).rgb);\n"
3303 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3304 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale));\n"
3305 "#else\n"
3306 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3307 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3308 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale).rgb);\n"
3309 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3310 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale));\n"
3311 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3312 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3313 "//     color.r = half(shadowmaptc.z);\n"
3314 "#endif\n"
3315 "//     color.r = 1;\n"
3316 "#endif\n"
3317 "//     color.rgb = half3(1,1,1);\n"
3318 "#endif // MODE_LIGHTSOURCE\n"
3319 "\n"
3320 "\n"
3321 "\n"
3322 "\n"
3323 "#ifdef MODE_LIGHTDIRECTION\n"
3324 "#define SHADING\n"
3325 "#ifdef USEDIFFUSE\n"
3326 "       half3 lightnormal = half3(normalize(LightVector));\n"
3327 "#endif\n"
3328 "#define lightcolor LightColor\n"
3329 "#endif // MODE_LIGHTDIRECTION\n"
3330 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3331 "#define SHADING\n"
3332 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3333 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3334 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3335 "       // convert modelspace light vector to tangentspace\n"
3336 "       half3 lightnormal;\n"
3337 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3338 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3339 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3340 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3341 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3342 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3343 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3344 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3345 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3346 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3347 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3348 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3349 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3350 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3351 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3352 "#define SHADING\n"
3353 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3354 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3355 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3356 "#endif\n"
3357 "\n"
3358 "\n"
3359 "\n"
3360 "\n"
3361 "#ifdef MODE_LIGHTMAP\n"
3362 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3363 "#endif // MODE_LIGHTMAP\n"
3364 "#ifdef MODE_VERTEXCOLOR\n"
3365 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3366 "#endif // MODE_VERTEXCOLOR\n"
3367 "#ifdef MODE_FLATCOLOR\n"
3368 "       color.rgb = diffusetex * Color_Ambient;\n"
3369 "#endif // MODE_FLATCOLOR\n"
3370 "\n"
3371 "\n"
3372 "\n"
3373 "\n"
3374 "#ifdef SHADING\n"
3375 "# ifdef USEDIFFUSE\n"
3376 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3377 "#  ifdef USESPECULAR\n"
3378 "#   ifdef USEEXACTSPECULARMATH\n"
3379 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3380 "#   else\n"
3381 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3382 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3383 "#   endif\n"
3384 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3385 "#  else\n"
3386 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3387 "#  endif\n"
3388 "# else\n"
3389 "       color.rgb = diffusetex * Color_Ambient;\n"
3390 "# endif\n"
3391 "#endif\n"
3392 "\n"
3393 "#ifdef USESHADOWMAPORTHO\n"
3394 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3395 "# if defined(USESHADOWMAP2D)\n"
3396 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3397 "# endif\n"
3398 "# if defined(USESHADOWMAPRECT)\n"
3399 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3400 "# endif\n"
3401 "       );\n"
3402 "#endif\n"
3403 "\n"
3404 "#ifdef USEDEFERREDLIGHTMAP\n"
3405 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3406 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3407 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3408 "#endif\n"
3409 "\n"
3410 "#ifdef USEGLOW\n"
3411 "#ifdef USEVERTEXTEXTUREBLEND\n"
3412 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3413 "#else\n"
3414 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3415 "#endif\n"
3416 "#endif\n"
3417 "\n"
3418 "#ifdef USEFOG\n"
3419 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3420 "#endif\n"
3421 "\n"
3422 "       // 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"
3423 "#ifdef USEREFLECTION\n"
3424 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3425 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3426 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3427 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3428 "       // FIXME temporary hack to detect the case that the reflection\n"
3429 "       // gets blackened at edges due to leaving the area that contains actual\n"
3430 "       // content.\n"
3431 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3432 "       // 'appening.\n"
3433 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3434 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3435 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3436 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3437 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3438 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3439 "#endif\n"
3440 "\n"
3441 "       gl_FragColor = float4(color);\n"
3442 "}\n"
3443 "#endif // FRAGMENT_SHADER\n"
3444 "\n"
3445 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3446 "#endif // !MODE_DEFERREDGEOMETRY\n"
3447 "#endif // !MODE_WATER\n"
3448 "#endif // !MODE_REFRACTION\n"
3449 "#endif // !MODE_BLOOMBLUR\n"
3450 "#endif // !MODE_GENERIC\n"
3451 "#endif // !MODE_POSTPROCESS\n"
3452 "#endif // !MODE_SHOWDEPTH\n"
3453 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3454 ;
3455
3456 char *glslshaderstring = NULL;
3457 char *cgshaderstring = NULL;
3458 char *hlslshaderstring = NULL;
3459
3460 //=======================================================================================================================================================
3461
3462 typedef struct shaderpermutationinfo_s
3463 {
3464         const char *pretext;
3465         const char *name;
3466 }
3467 shaderpermutationinfo_t;
3468
3469 typedef struct shadermodeinfo_s
3470 {
3471         const char *vertexfilename;
3472         const char *geometryfilename;
3473         const char *fragmentfilename;
3474         const char *pretext;
3475         const char *name;
3476 }
3477 shadermodeinfo_t;
3478
3479 typedef enum shaderpermutation_e
3480 {
3481         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3482         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3483         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3484         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3485         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3486         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3487         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3488         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3489         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3490         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3491         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3492         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3493         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3494         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3495         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3496         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3497         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3498         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3499         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3500         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3501         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3502         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3503         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3504         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3505         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3506         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3507         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3508         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3509         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3510         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3511         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3512 }
3513 shaderpermutation_t;
3514
3515 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3516 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3517 {
3518         {"#define USEDIFFUSE\n", " diffuse"},
3519         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3520         {"#define USEVIEWTINT\n", " viewtint"},
3521         {"#define USECOLORMAPPING\n", " colormapping"},
3522         {"#define USESATURATION\n", " saturation"},
3523         {"#define USEFOGINSIDE\n", " foginside"},
3524         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3525         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3526         {"#define USEGAMMARAMPS\n", " gammaramps"},
3527         {"#define USECUBEFILTER\n", " cubefilter"},
3528         {"#define USEGLOW\n", " glow"},
3529         {"#define USEBLOOM\n", " bloom"},
3530         {"#define USESPECULAR\n", " specular"},
3531         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3532         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3533         {"#define USEREFLECTION\n", " reflection"},
3534         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3535         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3536         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3537         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3538         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3539         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3540         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3541         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3542         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3543         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3544         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3545         {"#define USEALPHAKILL\n", " alphakill"},
3546         {"#define USEREFLECTCUBE\n", " reflectcube"},
3547 };
3548
3549 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3550 typedef enum shadermode_e
3551 {
3552         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3553         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3554         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3555         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3556         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3557         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3558         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3559         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3560         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3561         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3562         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3563         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3564         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3565         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3566         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3567         SHADERMODE_COUNT
3568 }
3569 shadermode_t;
3570
3571 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3572 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3573 {
3574         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3575         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3576         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3577         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3578         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3579         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3580         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3581         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3582         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3583         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3584         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3585         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3586         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3587         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3588         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3589 };
3590
3591 #ifdef SUPPORTCG
3592 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3593 {
3594         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3595         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3596         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3597         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3598         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3599         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3600         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3601         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3602         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3603         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3604         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3605         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3606         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3607         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3608         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3609 };
3610 #endif
3611
3612 #ifdef SUPPORTD3D
3613 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3614 {
3615         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3616         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3617         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3618         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3619         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3620         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3621         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3622         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3623         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3624         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3625         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3626         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3627         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3628         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3629         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3630 };
3631 #endif
3632
3633 struct r_glsl_permutation_s;
3634 typedef struct r_glsl_permutation_s
3635 {
3636         /// hash lookup data
3637         struct r_glsl_permutation_s *hashnext;
3638         unsigned int mode;
3639         unsigned int permutation;
3640
3641         /// indicates if we have tried compiling this permutation already
3642         qboolean compiled;
3643         /// 0 if compilation failed
3644         int program;
3645         /// locations of detected uniforms in program object, or -1 if not found
3646         int loc_Texture_First;
3647         int loc_Texture_Second;
3648         int loc_Texture_GammaRamps;
3649         int loc_Texture_Normal;
3650         int loc_Texture_Color;
3651         int loc_Texture_Gloss;
3652         int loc_Texture_Glow;
3653         int loc_Texture_SecondaryNormal;
3654         int loc_Texture_SecondaryColor;
3655         int loc_Texture_SecondaryGloss;
3656         int loc_Texture_SecondaryGlow;
3657         int loc_Texture_Pants;
3658         int loc_Texture_Shirt;
3659         int loc_Texture_FogHeightTexture;
3660         int loc_Texture_FogMask;
3661         int loc_Texture_Lightmap;
3662         int loc_Texture_Deluxemap;
3663         int loc_Texture_Attenuation;
3664         int loc_Texture_Cube;
3665         int loc_Texture_Refraction;
3666         int loc_Texture_Reflection;
3667         int loc_Texture_ShadowMapRect;
3668         int loc_Texture_ShadowMapCube;
3669         int loc_Texture_ShadowMap2D;
3670         int loc_Texture_CubeProjection;
3671         int loc_Texture_ScreenDepth;
3672         int loc_Texture_ScreenNormalMap;
3673         int loc_Texture_ScreenDiffuse;
3674         int loc_Texture_ScreenSpecular;
3675         int loc_Texture_ReflectMask;
3676         int loc_Texture_ReflectCube;
3677         int loc_Alpha;
3678         int loc_BloomBlur_Parameters;
3679         int loc_ClientTime;
3680         int loc_Color_Ambient;
3681         int loc_Color_Diffuse;
3682         int loc_Color_Specular;
3683         int loc_Color_Glow;
3684         int loc_Color_Pants;
3685         int loc_Color_Shirt;
3686         int loc_DeferredColor_Ambient;
3687         int loc_DeferredColor_Diffuse;
3688         int loc_DeferredColor_Specular;
3689         int loc_DeferredMod_Diffuse;
3690         int loc_DeferredMod_Specular;
3691         int loc_DistortScaleRefractReflect;
3692         int loc_EyePosition;
3693         int loc_FogColor;
3694         int loc_FogHeightFade;
3695         int loc_FogPlane;
3696         int loc_FogPlaneViewDist;
3697         int loc_FogRangeRecip;
3698         int loc_LightColor;
3699         int loc_LightDir;
3700         int loc_LightPosition;
3701         int loc_OffsetMapping_Scale;
3702         int loc_PixelSize;
3703         int loc_ReflectColor;
3704         int loc_ReflectFactor;
3705         int loc_ReflectOffset;
3706         int loc_RefractColor;
3707         int loc_Saturation;
3708         int loc_ScreenCenterRefractReflect;
3709         int loc_ScreenScaleRefractReflect;
3710         int loc_ScreenToDepth;
3711         int loc_ShadowMap_Parameters;
3712         int loc_ShadowMap_TextureScale;
3713         int loc_SpecularPower;
3714         int loc_UserVec1;
3715         int loc_UserVec2;
3716         int loc_UserVec3;
3717         int loc_UserVec4;
3718         int loc_ViewTintColor;
3719         int loc_ViewToLight;
3720         int loc_ModelToLight;
3721         int loc_TexMatrix;
3722         int loc_BackgroundTexMatrix;
3723         int loc_ModelViewProjectionMatrix;
3724         int loc_ModelViewMatrix;
3725         int loc_PixelToScreenTexCoord;
3726         int loc_ModelToReflectCube;
3727         int loc_ShadowMapMatrix;
3728         int loc_BloomColorSubtract;
3729 }
3730 r_glsl_permutation_t;
3731
3732 #define SHADERPERMUTATION_HASHSIZE 256
3733
3734 /// information about each possible shader permutation
3735 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3736 /// currently selected permutation
3737 r_glsl_permutation_t *r_glsl_permutation;
3738 /// storage for permutations linked in the hash table
3739 memexpandablearray_t r_glsl_permutationarray;
3740
3741 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3742 {
3743         //unsigned int hashdepth = 0;
3744         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3745         r_glsl_permutation_t *p;
3746         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3747         {
3748                 if (p->mode == mode && p->permutation == permutation)
3749                 {
3750                         //if (hashdepth > 10)
3751                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3752                         return p;
3753                 }
3754                 //hashdepth++;
3755         }
3756         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3757         p->mode = mode;
3758         p->permutation = permutation;
3759         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3760         r_glsl_permutationhash[mode][hashindex] = p;
3761         //if (hashdepth > 10)
3762         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3763         return p;
3764 }
3765
3766 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3767 {
3768         char *shaderstring;
3769         if (!filename || !filename[0])
3770                 return NULL;
3771         if (!strcmp(filename, "glsl/default.glsl"))
3772         {
3773                 if (!glslshaderstring)
3774                 {
3775                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3776                         if (glslshaderstring)
3777                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3778                         else
3779                                 glslshaderstring = (char *)builtinshaderstring;
3780                 }
3781                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3782                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3783                 return shaderstring;
3784         }
3785         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3786         if (shaderstring)
3787         {
3788                 if (printfromdisknotice)
3789                         Con_DPrintf("from disk %s... ", filename);
3790                 return shaderstring;
3791         }
3792         return shaderstring;
3793 }
3794
3795 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3796 {
3797         int i;
3798         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3799         int vertstrings_count = 0;
3800         int geomstrings_count = 0;
3801         int fragstrings_count = 0;
3802         char *vertexstring, *geometrystring, *fragmentstring;
3803         const char *vertstrings_list[32+3];
3804         const char *geomstrings_list[32+3];
3805         const char *fragstrings_list[32+3];
3806         char permutationname[256];
3807
3808         if (p->compiled)
3809                 return;
3810         p->compiled = true;
3811         p->program = 0;
3812
3813         permutationname[0] = 0;
3814         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3815         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3816         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3817
3818         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3819
3820         // the first pretext is which type of shader to compile as
3821         // (later these will all be bound together as a program object)
3822         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3823         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3824         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3825
3826         // the second pretext is the mode (for example a light source)
3827         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3828         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3829         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3830         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3831
3832         // now add all the permutation pretexts
3833         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3834         {
3835                 if (permutation & (1<<i))
3836                 {
3837                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3838                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3839                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3840                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3841                 }
3842                 else
3843                 {
3844                         // keep line numbers correct
3845                         vertstrings_list[vertstrings_count++] = "\n";
3846                         geomstrings_list[geomstrings_count++] = "\n";
3847                         fragstrings_list[fragstrings_count++] = "\n";
3848                 }
3849         }
3850
3851         // now append the shader text itself
3852         vertstrings_list[vertstrings_count++] = vertexstring;
3853         geomstrings_list[geomstrings_count++] = geometrystring;
3854         fragstrings_list[fragstrings_count++] = fragmentstring;
3855
3856         // if any sources were NULL, clear the respective list
3857         if (!vertexstring)
3858                 vertstrings_count = 0;
3859         if (!geometrystring)
3860                 geomstrings_count = 0;
3861         if (!fragmentstring)
3862                 fragstrings_count = 0;
3863
3864         // compile the shader program
3865         if (vertstrings_count + geomstrings_count + fragstrings_count)
3866                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3867         if (p->program)
3868         {
3869                 CHECKGLERROR
3870                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3871                 // look up all the uniform variable names we care about, so we don't
3872                 // have to look them up every time we set them
3873
3874                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3875                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3876                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3877                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3878                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3879                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3880                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3881                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3882                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3883                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3884                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3885                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3886                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3887                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3888                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3889                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3890                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3891                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3892                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3893                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3894                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3895                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3896                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3897                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3898                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3899                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3900                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3901                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3902                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3903                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3904                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3905                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3906                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3907                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3908                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3909                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3910                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3911                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3912                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3913                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3914                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3915                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3916                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3917                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3918                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3919                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3920                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3921                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3922                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3923                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3924                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3925                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3926                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3927                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3928                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3929                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3930                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3931                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3932                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3933                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3934                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3935                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3936                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3937                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3938                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3939                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3940                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3941                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3942                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3943                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3944                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3945                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3946                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3947                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3948                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3949                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3950                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3951                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3952                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3953                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3954                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3955                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3956                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3957                 // initialize the samplers to refer to the texture units we use
3958                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3959                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3960                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3961                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3962                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3963                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3964                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3965                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3966                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3967                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3968                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3969                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3970                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3971                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3972                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3973                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3974                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3975                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3976                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3977                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3978                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3979                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3980                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3981                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3982                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3983                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3984                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3985                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3986                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3987                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3988                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3989                 CHECKGLERROR
3990                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3991         }
3992         else
3993                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3994
3995         // free the strings
3996         if (vertexstring)
3997                 Mem_Free(vertexstring);
3998         if (geometrystring)
3999                 Mem_Free(geometrystring);
4000         if (fragmentstring)
4001                 Mem_Free(fragmentstring);
4002 }
4003
4004 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
4005 {
4006         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
4007         if (r_glsl_permutation != perm)
4008         {
4009                 r_glsl_permutation = perm;
4010                 if (!r_glsl_permutation->program)
4011                 {
4012                         if (!r_glsl_permutation->compiled)
4013                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4014                         if (!r_glsl_permutation->program)
4015                         {
4016                                 // remove features until we find a valid permutation
4017                                 int i;
4018                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4019                                 {
4020                                         // reduce i more quickly whenever it would not remove any bits
4021                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4022                                         if (!(permutation & j))
4023                                                 continue;
4024                                         permutation -= j;
4025                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4026                                         if (!r_glsl_permutation->compiled)
4027                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4028                                         if (r_glsl_permutation->program)
4029                                                 break;
4030                                 }
4031                                 if (i >= SHADERPERMUTATION_COUNT)
4032                                 {
4033                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4034                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4035                                         qglUseProgramObjectARB(0);CHECKGLERROR
4036                                         return; // no bit left to clear, entire mode is broken
4037                                 }
4038                         }
4039                 }
4040                 CHECKGLERROR
4041                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
4042         }
4043         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4044         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4045         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4046 }
4047
4048 #ifdef SUPPORTCG
4049 #include <Cg/cgGL.h>
4050 struct r_cg_permutation_s;
4051 typedef struct r_cg_permutation_s
4052 {
4053         /// hash lookup data
4054         struct r_cg_permutation_s *hashnext;
4055         unsigned int mode;
4056         unsigned int permutation;
4057
4058         /// indicates if we have tried compiling this permutation already
4059         qboolean compiled;
4060         /// 0 if compilation failed
4061         CGprogram vprogram;
4062         CGprogram fprogram;
4063         /// locations of detected parameters in programs, or NULL if not found
4064         CGparameter vp_EyePosition;
4065         CGparameter vp_FogPlane;
4066         CGparameter vp_LightDir;
4067         CGparameter vp_LightPosition;
4068         CGparameter vp_ModelToLight;
4069         CGparameter vp_TexMatrix;
4070         CGparameter vp_BackgroundTexMatrix;
4071         CGparameter vp_ModelViewProjectionMatrix;
4072         CGparameter vp_ModelViewMatrix;
4073         CGparameter vp_ShadowMapMatrix;
4074
4075         CGparameter fp_Texture_First;
4076         CGparameter fp_Texture_Second;
4077         CGparameter fp_Texture_GammaRamps;
4078         CGparameter fp_Texture_Normal;
4079         CGparameter fp_Texture_Color;
4080         CGparameter fp_Texture_Gloss;
4081         CGparameter fp_Texture_Glow;
4082         CGparameter fp_Texture_SecondaryNormal;
4083         CGparameter fp_Texture_SecondaryColor;
4084         CGparameter fp_Texture_SecondaryGloss;
4085         CGparameter fp_Texture_SecondaryGlow;
4086         CGparameter fp_Texture_Pants;
4087         CGparameter fp_Texture_Shirt;
4088         CGparameter fp_Texture_FogHeightTexture;
4089         CGparameter fp_Texture_FogMask;
4090         CGparameter fp_Texture_Lightmap;
4091         CGparameter fp_Texture_Deluxemap;
4092         CGparameter fp_Texture_Attenuation;
4093         CGparameter fp_Texture_Cube;
4094         CGparameter fp_Texture_Refraction;
4095         CGparameter fp_Texture_Reflection;
4096         CGparameter fp_Texture_ShadowMapRect;
4097         CGparameter fp_Texture_ShadowMapCube;
4098         CGparameter fp_Texture_ShadowMap2D;
4099         CGparameter fp_Texture_CubeProjection;
4100         CGparameter fp_Texture_ScreenDepth;
4101         CGparameter fp_Texture_ScreenNormalMap;
4102         CGparameter fp_Texture_ScreenDiffuse;
4103         CGparameter fp_Texture_ScreenSpecular;
4104         CGparameter fp_Texture_ReflectMask;
4105         CGparameter fp_Texture_ReflectCube;
4106         CGparameter fp_Alpha;
4107         CGparameter fp_BloomBlur_Parameters;
4108         CGparameter fp_ClientTime;
4109         CGparameter fp_Color_Ambient;
4110         CGparameter fp_Color_Diffuse;
4111         CGparameter fp_Color_Specular;
4112         CGparameter fp_Color_Glow;
4113         CGparameter fp_Color_Pants;
4114         CGparameter fp_Color_Shirt;
4115         CGparameter fp_DeferredColor_Ambient;
4116         CGparameter fp_DeferredColor_Diffuse;
4117         CGparameter fp_DeferredColor_Specular;
4118         CGparameter fp_DeferredMod_Diffuse;
4119         CGparameter fp_DeferredMod_Specular;
4120         CGparameter fp_DistortScaleRefractReflect;
4121         CGparameter fp_EyePosition;
4122         CGparameter fp_FogColor;
4123         CGparameter fp_FogHeightFade;
4124         CGparameter fp_FogPlane;
4125         CGparameter fp_FogPlaneViewDist;
4126         CGparameter fp_FogRangeRecip;
4127         CGparameter fp_LightColor;
4128         CGparameter fp_LightDir;
4129         CGparameter fp_LightPosition;
4130         CGparameter fp_OffsetMapping_Scale;
4131         CGparameter fp_PixelSize;
4132         CGparameter fp_ReflectColor;
4133         CGparameter fp_ReflectFactor;
4134         CGparameter fp_ReflectOffset;
4135         CGparameter fp_RefractColor;
4136         CGparameter fp_Saturation;
4137         CGparameter fp_ScreenCenterRefractReflect;
4138         CGparameter fp_ScreenScaleRefractReflect;
4139         CGparameter fp_ScreenToDepth;
4140         CGparameter fp_ShadowMap_Parameters;
4141         CGparameter fp_ShadowMap_TextureScale;
4142         CGparameter fp_SpecularPower;
4143         CGparameter fp_UserVec1;
4144         CGparameter fp_UserVec2;
4145         CGparameter fp_UserVec3;
4146         CGparameter fp_UserVec4;
4147         CGparameter fp_ViewTintColor;
4148         CGparameter fp_ViewToLight;
4149         CGparameter fp_PixelToScreenTexCoord;
4150         CGparameter fp_ModelToReflectCube;
4151         CGparameter fp_BloomColorSubtract;
4152 }
4153 r_cg_permutation_t;
4154
4155 /// information about each possible shader permutation
4156 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4157 /// currently selected permutation
4158 r_cg_permutation_t *r_cg_permutation;
4159 /// storage for permutations linked in the hash table
4160 memexpandablearray_t r_cg_permutationarray;
4161
4162 #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));}}
4163
4164 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4165 {
4166         //unsigned int hashdepth = 0;
4167         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4168         r_cg_permutation_t *p;
4169         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4170         {
4171                 if (p->mode == mode && p->permutation == permutation)
4172                 {
4173                         //if (hashdepth > 10)
4174                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4175                         return p;
4176                 }
4177                 //hashdepth++;
4178         }
4179         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4180         p->mode = mode;
4181         p->permutation = permutation;
4182         p->hashnext = r_cg_permutationhash[mode][hashindex];
4183         r_cg_permutationhash[mode][hashindex] = p;
4184         //if (hashdepth > 10)
4185         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4186         return p;
4187 }
4188
4189 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4190 {
4191         char *shaderstring;
4192         if (!filename || !filename[0])
4193                 return NULL;
4194         if (!strcmp(filename, "cg/default.cg"))
4195         {
4196                 if (!cgshaderstring)
4197                 {
4198                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4199                         if (cgshaderstring)
4200                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4201                         else
4202                                 cgshaderstring = (char *)builtincgshaderstring;
4203                 }
4204                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4205                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4206                 return shaderstring;
4207         }
4208         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4209         if (shaderstring)
4210         {
4211                 if (printfromdisknotice)
4212                         Con_DPrintf("from disk %s... ", filename);
4213                 return shaderstring;
4214         }
4215         return shaderstring;
4216 }
4217
4218 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4219 {
4220         // TODO: load or create .fp and .vp shader files
4221 }
4222
4223 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4224 {
4225         int i;
4226         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4227         int vertstrings_count = 0, vertstring_length = 0;
4228         int geomstrings_count = 0, geomstring_length = 0;
4229         int fragstrings_count = 0, fragstring_length = 0;
4230         char *t;
4231         char *vertexstring, *geometrystring, *fragmentstring;
4232         char *vertstring, *geomstring, *fragstring;
4233         const char *vertstrings_list[32+3];
4234         const char *geomstrings_list[32+3];
4235         const char *fragstrings_list[32+3];
4236         char permutationname[256];
4237         char cachename[256];
4238         CGprofile vertexProfile;
4239         CGprofile fragmentProfile;
4240
4241         if (p->compiled)
4242                 return;
4243         p->compiled = true;
4244         p->vprogram = NULL;
4245         p->fprogram = NULL;
4246
4247         permutationname[0] = 0;
4248         cachename[0] = 0;
4249         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4250         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4251         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4252
4253         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4254         strlcat(cachename, "cg/", sizeof(cachename));
4255
4256         // the first pretext is which type of shader to compile as
4257         // (later these will all be bound together as a program object)
4258         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4259         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4260         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4261
4262         // the second pretext is the mode (for example a light source)
4263         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4264         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4265         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4266         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4267         strlcat(cachename, modeinfo->name, sizeof(cachename));
4268
4269         // now add all the permutation pretexts
4270         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4271         {
4272                 if (permutation & (1<<i))
4273                 {
4274                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4275                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4276                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4277                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4278                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4279                 }
4280                 else
4281                 {
4282                         // keep line numbers correct
4283                         vertstrings_list[vertstrings_count++] = "\n";
4284                         geomstrings_list[geomstrings_count++] = "\n";
4285                         fragstrings_list[fragstrings_count++] = "\n";
4286                 }
4287         }
4288
4289         // replace spaces in the cachename with _ characters
4290         for (i = 0;cachename[i];i++)
4291                 if (cachename[i] == ' ')
4292                         cachename[i] = '_';
4293
4294         // now append the shader text itself
4295         vertstrings_list[vertstrings_count++] = vertexstring;
4296         geomstrings_list[geomstrings_count++] = geometrystring;
4297         fragstrings_list[fragstrings_count++] = fragmentstring;
4298
4299         // if any sources were NULL, clear the respective list
4300         if (!vertexstring)
4301                 vertstrings_count = 0;
4302         if (!geometrystring)
4303                 geomstrings_count = 0;
4304         if (!fragmentstring)
4305                 fragstrings_count = 0;
4306
4307         vertstring_length = 0;
4308         for (i = 0;i < vertstrings_count;i++)
4309                 vertstring_length += strlen(vertstrings_list[i]);
4310         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4311         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4312                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4313
4314         geomstring_length = 0;
4315         for (i = 0;i < geomstrings_count;i++)
4316                 geomstring_length += strlen(geomstrings_list[i]);
4317         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4318         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4319                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4320
4321         fragstring_length = 0;
4322         for (i = 0;i < fragstrings_count;i++)
4323                 fragstring_length += strlen(fragstrings_list[i]);
4324         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4325         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4326                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4327
4328         CHECKGLERROR
4329         CHECKCGERROR
4330         //vertexProfile = CG_PROFILE_ARBVP1;
4331         //fragmentProfile = CG_PROFILE_ARBFP1;
4332         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4333         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4334         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4335         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4336         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4337         CHECKGLERROR
4338
4339         // try to load the cached shader, or generate one
4340         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4341
4342         // if caching failed, do a dynamic compile for now
4343         CHECKCGERROR
4344         if (vertstring[0] && !p->vprogram)
4345                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4346         CHECKCGERROR
4347         if (fragstring[0] && !p->fprogram)
4348                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4349         CHECKCGERROR
4350
4351         // look up all the uniform variable names we care about, so we don't
4352         // have to look them up every time we set them
4353         if (p->vprogram)
4354         {
4355                 CHECKCGERROR
4356                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4357                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4358                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4359                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4360                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4361                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4362                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4363                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4364                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4365                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4366                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4367                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4368                 CHECKCGERROR
4369         }
4370         if (p->fprogram)
4371         {
4372                 CHECKCGERROR
4373                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4374                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4375                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4376                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4377                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4378                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4379                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4380                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4381                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4382                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4383                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4384                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4385                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4386                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4387                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4388                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4389                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4390                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4391                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4392                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4393                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4394                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4395                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4396                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4397                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4398                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4399                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4400                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4401                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4402                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4403                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4404                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4405                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4406                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4407                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4408                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4409                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4410                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4411                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4412                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4413                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4414                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4415                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4416                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4417                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4418                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4419                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4420                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4421                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4422                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4423                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4424                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4425                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4426                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4427                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4428                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4429                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4430                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4431                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4432                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4433                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4434                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4435                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4436                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4437                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4438                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4439                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4440                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4441                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4442                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4443                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4444                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4445                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4446                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4447                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4448                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4449                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4450                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4451                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4452                 CHECKCGERROR
4453         }
4454
4455         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4456                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4457         else
4458                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4459
4460         // free the strings
4461         if (vertstring)
4462                 Mem_Free(vertstring);
4463         if (geomstring)
4464                 Mem_Free(geomstring);
4465         if (fragstring)
4466                 Mem_Free(fragstring);
4467         if (vertexstring)
4468                 Mem_Free(vertexstring);
4469         if (geometrystring)
4470                 Mem_Free(geometrystring);
4471         if (fragmentstring)
4472                 Mem_Free(fragmentstring);
4473 }
4474
4475 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4476 {
4477         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4478         CHECKGLERROR
4479         CHECKCGERROR
4480         if (r_cg_permutation != perm)
4481         {
4482                 r_cg_permutation = perm;
4483                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4484                 {
4485                         if (!r_cg_permutation->compiled)
4486                                 R_CG_CompilePermutation(perm, mode, permutation);
4487                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4488                         {
4489                                 // remove features until we find a valid permutation
4490                                 int i;
4491                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4492                                 {
4493                                         // reduce i more quickly whenever it would not remove any bits
4494                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4495                                         if (!(permutation & j))
4496                                                 continue;
4497                                         permutation -= j;
4498                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4499                                         if (!r_cg_permutation->compiled)
4500                                                 R_CG_CompilePermutation(perm, mode, permutation);
4501                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4502                                                 break;
4503                                 }
4504                                 if (i >= SHADERPERMUTATION_COUNT)
4505                                 {
4506                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4507                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4508                                         return; // no bit left to clear, entire mode is broken
4509                                 }
4510                         }
4511                 }
4512                 CHECKGLERROR
4513                 CHECKCGERROR
4514                 if (r_cg_permutation->vprogram)
4515                 {
4516                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4517                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4518                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4519                 }
4520                 else
4521                 {
4522                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4523                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4524                 }
4525                 if (r_cg_permutation->fprogram)
4526                 {
4527                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4528                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4529                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4530                 }
4531                 else
4532                 {
4533                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4534                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4535                 }
4536         }
4537         CHECKCGERROR
4538         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4539         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4540         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4541 }
4542
4543 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4544 {
4545         cgGLSetTextureParameter(param, R_GetTexture(tex));
4546         cgGLEnableTextureParameter(param);
4547 }
4548 #endif
4549
4550 #ifdef SUPPORTD3D
4551
4552 #ifdef SUPPORTD3D
4553 #include <d3d9.h>
4554 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4555 extern D3DCAPS9 vid_d3d9caps;
4556 #endif
4557
4558 struct r_hlsl_permutation_s;
4559 typedef struct r_hlsl_permutation_s
4560 {
4561         /// hash lookup data
4562         struct r_hlsl_permutation_s *hashnext;
4563         unsigned int mode;
4564         unsigned int permutation;
4565
4566         /// indicates if we have tried compiling this permutation already
4567         qboolean compiled;
4568         /// NULL if compilation failed
4569         IDirect3DVertexShader9 *vertexshader;
4570         IDirect3DPixelShader9 *pixelshader;
4571 }
4572 r_hlsl_permutation_t;
4573
4574 typedef enum D3DVSREGISTER_e
4575 {
4576         D3DVSREGISTER_TexMatrix = 0, // float4x4
4577         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4578         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4579         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4580         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4581         D3DVSREGISTER_ModelToLight = 20, // float4x4
4582         D3DVSREGISTER_EyePosition = 24,
4583         D3DVSREGISTER_FogPlane = 25,
4584         D3DVSREGISTER_LightDir = 26,
4585         D3DVSREGISTER_LightPosition = 27,
4586 }
4587 D3DVSREGISTER_t;
4588
4589 typedef enum D3DPSREGISTER_e
4590 {
4591         D3DPSREGISTER_Alpha = 0,
4592         D3DPSREGISTER_BloomBlur_Parameters = 1,
4593         D3DPSREGISTER_ClientTime = 2,
4594         D3DPSREGISTER_Color_Ambient = 3,
4595         D3DPSREGISTER_Color_Diffuse = 4,
4596         D3DPSREGISTER_Color_Specular = 5,
4597         D3DPSREGISTER_Color_Glow = 6,
4598         D3DPSREGISTER_Color_Pants = 7,
4599         D3DPSREGISTER_Color_Shirt = 8,
4600         D3DPSREGISTER_DeferredColor_Ambient = 9,
4601         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4602         D3DPSREGISTER_DeferredColor_Specular = 11,
4603         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4604         D3DPSREGISTER_DeferredMod_Specular = 13,
4605         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4606         D3DPSREGISTER_EyePosition = 15, // unused
4607         D3DPSREGISTER_FogColor = 16,
4608         D3DPSREGISTER_FogHeightFade = 17,
4609         D3DPSREGISTER_FogPlane = 18,
4610         D3DPSREGISTER_FogPlaneViewDist = 19,
4611         D3DPSREGISTER_FogRangeRecip = 20,
4612         D3DPSREGISTER_LightColor = 21,
4613         D3DPSREGISTER_LightDir = 22, // unused
4614         D3DPSREGISTER_LightPosition = 23,
4615         D3DPSREGISTER_OffsetMapping_Scale = 24,
4616         D3DPSREGISTER_PixelSize = 25,
4617         D3DPSREGISTER_ReflectColor = 26,
4618         D3DPSREGISTER_ReflectFactor = 27,
4619         D3DPSREGISTER_ReflectOffset = 28,
4620         D3DPSREGISTER_RefractColor = 29,
4621         D3DPSREGISTER_Saturation = 30,
4622         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4623         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4624         D3DPSREGISTER_ScreenToDepth = 33,
4625         D3DPSREGISTER_ShadowMap_Parameters = 34,
4626         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4627         D3DPSREGISTER_SpecularPower = 36,
4628         D3DPSREGISTER_UserVec1 = 37,
4629         D3DPSREGISTER_UserVec2 = 38,
4630         D3DPSREGISTER_UserVec3 = 39,
4631         D3DPSREGISTER_UserVec4 = 40,
4632         D3DPSREGISTER_ViewTintColor = 41,
4633         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4634         D3DPSREGISTER_BloomColorSubtract = 43,
4635         D3DPSREGISTER_ViewToLight = 44, // float4x4
4636         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4637         // next at 52
4638 }
4639 D3DPSREGISTER_t;
4640
4641 /// information about each possible shader permutation
4642 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4643 /// currently selected permutation
4644 r_hlsl_permutation_t *r_hlsl_permutation;
4645 /// storage for permutations linked in the hash table
4646 memexpandablearray_t r_hlsl_permutationarray;
4647
4648 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4649 {
4650         //unsigned int hashdepth = 0;
4651         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4652         r_hlsl_permutation_t *p;
4653         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4654         {
4655                 if (p->mode == mode && p->permutation == permutation)
4656                 {
4657                         //if (hashdepth > 10)
4658                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4659                         return p;
4660                 }
4661                 //hashdepth++;
4662         }
4663         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4664         p->mode = mode;
4665         p->permutation = permutation;
4666         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4667         r_hlsl_permutationhash[mode][hashindex] = p;
4668         //if (hashdepth > 10)
4669         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4670         return p;
4671 }
4672
4673 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4674 {
4675         char *shaderstring;
4676         if (!filename || !filename[0])
4677                 return NULL;
4678         if (!strcmp(filename, "hlsl/default.hlsl"))
4679         {
4680                 if (!hlslshaderstring)
4681                 {
4682                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4683                         if (hlslshaderstring)
4684                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4685                         else
4686                                 hlslshaderstring = (char *)builtincgshaderstring;
4687                 }
4688                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4689                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4690                 return shaderstring;
4691         }
4692         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4693         if (shaderstring)
4694         {
4695                 if (printfromdisknotice)
4696                         Con_DPrintf("from disk %s... ", filename);
4697                 return shaderstring;
4698         }
4699         return shaderstring;
4700 }
4701
4702 #include <d3dx9.h>
4703 //#include <d3dx9shader.h>
4704 //#include <d3dx9mesh.h>
4705
4706 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4707 {
4708         DWORD *vsbin = NULL;
4709         DWORD *psbin = NULL;
4710         fs_offset_t vsbinsize;
4711         fs_offset_t psbinsize;
4712 //      IDirect3DVertexShader9 *vs = NULL;
4713 //      IDirect3DPixelShader9 *ps = NULL;
4714         ID3DXBuffer *vslog = NULL;
4715         ID3DXBuffer *vsbuffer = NULL;
4716         ID3DXConstantTable *vsconstanttable = NULL;
4717         ID3DXBuffer *pslog = NULL;
4718         ID3DXBuffer *psbuffer = NULL;
4719         ID3DXConstantTable *psconstanttable = NULL;
4720         int vsresult = 0;
4721         int psresult = 0;
4722         char temp[MAX_INPUTLINE];
4723         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4724         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4725         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4726         vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4727         psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4728         if ((!vsbin && vertstring) || (!psbin && fragstring))
4729         {
4730                 const char* dllnames_d3dx9 [] =
4731                 {
4732                         "d3dx9_43.dll",
4733                         "d3dx9_42.dll",
4734                         "d3dx9_41.dll",
4735                         "d3dx9_40.dll",
4736                         "d3dx9_39.dll",
4737                         "d3dx9_38.dll",
4738                         "d3dx9_37.dll",
4739                         "d3dx9_36.dll",
4740                         "d3dx9_35.dll",
4741                         "d3dx9_34.dll",
4742                         "d3dx9_33.dll",
4743                         "d3dx9_32.dll",
4744                         "d3dx9_31.dll",
4745                         "d3dx9_30.dll",
4746                         "d3dx9_29.dll",
4747                         "d3dx9_28.dll",
4748                         "d3dx9_27.dll",
4749                         "d3dx9_26.dll",
4750                         "d3dx9_25.dll",
4751                         "d3dx9_24.dll",
4752                         NULL
4753                 };
4754                 dllhandle_t d3dx9_dll = NULL;
4755                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4756                 dllfunction_t d3dx9_dllfuncs[] =
4757                 {
4758                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4759                         {NULL, NULL}
4760                 };
4761                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4762                 {
4763                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4764                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4765                         if (vertstring && vertstring[0])
4766                         {
4767                                 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, 0, &vsbuffer, &vslog, &vsconstanttable);
4768                                 if (vsbuffer)
4769                                 {
4770                                         vsbinsize = vsbuffer->GetBufferSize();
4771                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4772                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4773                                         vsbuffer->Release();
4774                                 }
4775                                 if (vslog)
4776                                 {
4777                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4778                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4779                                         vslog->Release();
4780                                 }
4781                         }
4782                         if (fragstring && fragstring[0])
4783                         {
4784                                 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, 0, &psbuffer, &pslog, &psconstanttable);
4785                                 if (psbuffer)
4786                                 {
4787                                         psbinsize = psbuffer->GetBufferSize();
4788                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4789                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4790                                         psbuffer->Release();
4791                                 }
4792                                 if (pslog)
4793                                 {
4794                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4795                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4796                                         pslog->Release();
4797                                 }
4798                         }
4799                         Sys_UnloadLibrary(&d3dx9_dll);
4800                 }
4801                 else
4802                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4803         }
4804         if (vsbin)
4805         {
4806                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4807                 if (FAILED(vsresult))
4808                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4809         }
4810         if (psbin)
4811         {
4812                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4813                 if (FAILED(psresult))
4814                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4815         }
4816         // free the shader data
4817         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4818         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4819 }
4820
4821 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4822 {
4823         int i;
4824         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4825         int vertstrings_count = 0, vertstring_length = 0;
4826         int geomstrings_count = 0, geomstring_length = 0;
4827         int fragstrings_count = 0, fragstring_length = 0;
4828         char *t;
4829         char *vertexstring, *geometrystring, *fragmentstring;
4830         char *vertstring, *geomstring, *fragstring;
4831         const char *vertstrings_list[32+3];
4832         const char *geomstrings_list[32+3];
4833         const char *fragstrings_list[32+3];
4834         char permutationname[256];
4835         char cachename[256];
4836
4837         if (p->compiled)
4838                 return;
4839         p->compiled = true;
4840         p->vertexshader = NULL;
4841         p->pixelshader = NULL;
4842
4843         permutationname[0] = 0;
4844         cachename[0] = 0;
4845         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4846         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4847         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4848
4849         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4850         strlcat(cachename, "hlsl/", sizeof(cachename));
4851
4852         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4853         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4854         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4855         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4856
4857         // the first pretext is which type of shader to compile as
4858         // (later these will all be bound together as a program object)
4859         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4860         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4861         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4862
4863         // the second pretext is the mode (for example a light source)
4864         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4865         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4866         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4867         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4868         strlcat(cachename, modeinfo->name, sizeof(cachename));
4869
4870         // now add all the permutation pretexts
4871         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4872         {
4873                 if (permutation & (1<<i))
4874                 {
4875                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4876                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4877                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4878                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4879                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4880                 }
4881                 else
4882                 {
4883                         // keep line numbers correct
4884                         vertstrings_list[vertstrings_count++] = "\n";
4885                         geomstrings_list[geomstrings_count++] = "\n";
4886                         fragstrings_list[fragstrings_count++] = "\n";
4887                 }
4888         }
4889
4890         // replace spaces in the cachename with _ characters
4891         for (i = 0;cachename[i];i++)
4892                 if (cachename[i] == ' ')
4893                         cachename[i] = '_';
4894
4895         // now append the shader text itself
4896         vertstrings_list[vertstrings_count++] = vertexstring;
4897         geomstrings_list[geomstrings_count++] = geometrystring;
4898         fragstrings_list[fragstrings_count++] = fragmentstring;
4899
4900         // if any sources were NULL, clear the respective list
4901         if (!vertexstring)
4902                 vertstrings_count = 0;
4903         if (!geometrystring)
4904                 geomstrings_count = 0;
4905         if (!fragmentstring)
4906                 fragstrings_count = 0;
4907
4908         vertstring_length = 0;
4909         for (i = 0;i < vertstrings_count;i++)
4910                 vertstring_length += strlen(vertstrings_list[i]);
4911         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4912         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4913                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4914
4915         geomstring_length = 0;
4916         for (i = 0;i < geomstrings_count;i++)
4917                 geomstring_length += strlen(geomstrings_list[i]);
4918         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4919         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4920                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4921
4922         fragstring_length = 0;
4923         for (i = 0;i < fragstrings_count;i++)
4924                 fragstring_length += strlen(fragstrings_list[i]);
4925         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4926         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4927                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4928
4929         // try to load the cached shader, or generate one
4930         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4931
4932         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4933                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4934         else
4935                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4936
4937         // free the strings
4938         if (vertstring)
4939                 Mem_Free(vertstring);
4940         if (geomstring)
4941                 Mem_Free(geomstring);
4942         if (fragstring)
4943                 Mem_Free(fragstring);
4944         if (vertexstring)
4945                 Mem_Free(vertexstring);
4946         if (geometrystring)
4947                 Mem_Free(geometrystring);
4948         if (fragmentstring)
4949                 Mem_Free(fragmentstring);
4950 }
4951
4952 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4953 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4954 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);}
4955 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);}
4956 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);}
4957 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);}
4958
4959 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4960 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4961 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);}
4962 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);}
4963 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);}
4964 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);}
4965
4966 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4967 {
4968         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4969         if (r_hlsl_permutation != perm)
4970         {
4971                 r_hlsl_permutation = perm;
4972                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4973                 {
4974                         if (!r_hlsl_permutation->compiled)
4975                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4976                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4977                         {
4978                                 // remove features until we find a valid permutation
4979                                 int i;
4980                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4981                                 {
4982                                         // reduce i more quickly whenever it would not remove any bits
4983                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4984                                         if (!(permutation & j))
4985                                                 continue;
4986                                         permutation -= j;
4987                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4988                                         if (!r_hlsl_permutation->compiled)
4989                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4990                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4991                                                 break;
4992                                 }
4993                                 if (i >= SHADERPERMUTATION_COUNT)
4994                                 {
4995                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4996                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4997                                         return; // no bit left to clear, entire mode is broken
4998                                 }
4999                         }
5000                 }
5001                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
5002                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
5003         }
5004         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5005         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5006         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
5007 }
5008 #endif
5009
5010 void R_GLSL_Restart_f(void)
5011 {
5012         unsigned int i, limit;
5013         if (glslshaderstring && glslshaderstring != builtinshaderstring)
5014                 Mem_Free(glslshaderstring);
5015         glslshaderstring = NULL;
5016         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
5017                 Mem_Free(cgshaderstring);
5018         cgshaderstring = NULL;
5019         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5020                 Mem_Free(hlslshaderstring);
5021         hlslshaderstring = NULL;
5022         switch(vid.renderpath)
5023         {
5024         case RENDERPATH_D3D9:
5025 #ifdef SUPPORTD3D
5026                 {
5027                         r_hlsl_permutation_t *p;
5028                         r_hlsl_permutation = NULL;
5029 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5030 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5031 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5032 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5033                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5034                         for (i = 0;i < limit;i++)
5035                         {
5036                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5037                                 {
5038                                         if (p->vertexshader)
5039                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5040                                         if (p->pixelshader)
5041                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5042                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5043                                 }
5044                         }
5045                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5046                 }
5047 #endif
5048                 break;
5049         case RENDERPATH_D3D10:
5050                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5051                 break;
5052         case RENDERPATH_D3D11:
5053                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5054                 break;
5055         case RENDERPATH_GL20:
5056                 {
5057                         r_glsl_permutation_t *p;
5058                         r_glsl_permutation = NULL;
5059                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5060                         for (i = 0;i < limit;i++)
5061                         {
5062                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5063                                 {
5064                                         GL_Backend_FreeProgram(p->program);
5065                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5066                                 }
5067                         }
5068                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5069                 }
5070                 break;
5071         case RENDERPATH_CGGL:
5072 #ifdef SUPPORTCG
5073                 {
5074                         r_cg_permutation_t *p;
5075                         r_cg_permutation = NULL;
5076                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5077                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5078                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5079                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5080                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5081                         for (i = 0;i < limit;i++)
5082                         {
5083                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5084                                 {
5085                                         if (p->vprogram)
5086                                                 cgDestroyProgram(p->vprogram);
5087                                         if (p->fprogram)
5088                                                 cgDestroyProgram(p->fprogram);
5089                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5090                                 }
5091                         }
5092                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5093                 }
5094 #endif
5095                 break;
5096         case RENDERPATH_GL13:
5097         case RENDERPATH_GL11:
5098                 break;
5099         }
5100 }
5101
5102 void R_GLSL_DumpShader_f(void)
5103 {
5104         int i;
5105         qfile_t *file;
5106
5107         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5108         if (file)
5109         {
5110                 FS_Print(file, "/* The engine may define the following macros:\n");
5111                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5112                 for (i = 0;i < SHADERMODE_COUNT;i++)
5113                         FS_Print(file, glslshadermodeinfo[i].pretext);
5114                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5115                         FS_Print(file, shaderpermutationinfo[i].pretext);
5116                 FS_Print(file, "*/\n");
5117                 FS_Print(file, builtinshaderstring);
5118                 FS_Close(file);
5119                 Con_Printf("glsl/default.glsl written\n");
5120         }
5121         else
5122                 Con_Printf("failed to write to glsl/default.glsl\n");
5123
5124 #ifdef SUPPORTCG
5125         file = FS_OpenRealFile("cg/default.cg", "w", false);
5126         if (file)
5127         {
5128                 FS_Print(file, "/* The engine may define the following macros:\n");
5129                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5130                 for (i = 0;i < SHADERMODE_COUNT;i++)
5131                         FS_Print(file, cgshadermodeinfo[i].pretext);
5132                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5133                         FS_Print(file, shaderpermutationinfo[i].pretext);
5134                 FS_Print(file, "*/\n");
5135                 FS_Print(file, builtincgshaderstring);
5136                 FS_Close(file);
5137                 Con_Printf("cg/default.cg written\n");
5138         }
5139         else
5140                 Con_Printf("failed to write to cg/default.cg\n");
5141 #endif
5142
5143 #ifdef SUPPORTD3D
5144         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5145         if (file)
5146         {
5147                 FS_Print(file, "/* The engine may define the following macros:\n");
5148                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5149                 for (i = 0;i < SHADERMODE_COUNT;i++)
5150                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5151                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5152                         FS_Print(file, shaderpermutationinfo[i].pretext);
5153                 FS_Print(file, "*/\n");
5154                 FS_Print(file, builtincgshaderstring);
5155                 FS_Close(file);
5156                 Con_Printf("hlsl/default.hlsl written\n");
5157         }
5158         else
5159                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5160 #endif
5161 }
5162
5163 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5164 {
5165         if (!second)
5166                 texturemode = GL_MODULATE;
5167         switch (vid.renderpath)
5168         {
5169         case RENDERPATH_D3D9:
5170 #ifdef SUPPORTD3D
5171                 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))));
5172                 R_Mesh_TexBind(GL20TU_FIRST , first );
5173                 R_Mesh_TexBind(GL20TU_SECOND, second);
5174 #endif
5175                 break;
5176         case RENDERPATH_D3D10:
5177                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5178                 break;
5179         case RENDERPATH_D3D11:
5180                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5181                 break;
5182         case RENDERPATH_GL20:
5183                 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))));
5184                 R_Mesh_TexBind(GL20TU_FIRST , first );
5185                 R_Mesh_TexBind(GL20TU_SECOND, second);
5186                 break;
5187         case RENDERPATH_CGGL:
5188 #ifdef SUPPORTCG
5189                 CHECKCGERROR
5190                 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))));
5191                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5192                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5193 #endif
5194                 break;
5195         case RENDERPATH_GL13:
5196                 R_Mesh_TexBind(0, first );
5197                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5198                 R_Mesh_TexBind(1, second);
5199                 if (second)
5200                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5201                 break;
5202         case RENDERPATH_GL11:
5203                 R_Mesh_TexBind(0, first );
5204                 break;
5205         }
5206 }
5207
5208 void R_SetupShader_DepthOrShadow(void)
5209 {
5210         switch (vid.renderpath)
5211         {
5212         case RENDERPATH_D3D9:
5213 #ifdef SUPPORTD3D
5214                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5215 #endif
5216                 break;
5217         case RENDERPATH_D3D10:
5218                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5219                 break;
5220         case RENDERPATH_D3D11:
5221                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5222                 break;
5223         case RENDERPATH_GL20:
5224                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5225                 break;
5226         case RENDERPATH_CGGL:
5227 #ifdef SUPPORTCG
5228                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5229 #endif
5230                 break;
5231         case RENDERPATH_GL13:
5232                 R_Mesh_TexBind(0, 0);
5233                 R_Mesh_TexBind(1, 0);
5234                 break;
5235         case RENDERPATH_GL11:
5236                 R_Mesh_TexBind(0, 0);
5237                 break;
5238         }
5239 }
5240
5241 void R_SetupShader_ShowDepth(void)
5242 {
5243         switch (vid.renderpath)
5244         {
5245         case RENDERPATH_D3D9:
5246 #ifdef SUPPORTHLSL
5247                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5248 #endif
5249                 break;
5250         case RENDERPATH_D3D10:
5251                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5252                 break;
5253         case RENDERPATH_D3D11:
5254                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5255                 break;
5256         case RENDERPATH_GL20:
5257                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5258                 break;
5259         case RENDERPATH_CGGL:
5260 #ifdef SUPPORTCG
5261                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5262 #endif
5263                 break;
5264         case RENDERPATH_GL13:
5265                 break;
5266         case RENDERPATH_GL11:
5267                 break;
5268         }
5269 }
5270
5271 extern qboolean r_shadow_usingdeferredprepass;
5272 extern cvar_t r_shadow_deferred_8bitrange;
5273 extern rtexture_t *r_shadow_attenuationgradienttexture;
5274 extern rtexture_t *r_shadow_attenuation2dtexture;
5275 extern rtexture_t *r_shadow_attenuation3dtexture;
5276 extern qboolean r_shadow_usingshadowmaprect;
5277 extern qboolean r_shadow_usingshadowmapcube;
5278 extern qboolean r_shadow_usingshadowmap2d;
5279 extern qboolean r_shadow_usingshadowmaportho;
5280 extern float r_shadow_shadowmap_texturescale[2];
5281 extern float r_shadow_shadowmap_parameters[4];
5282 extern qboolean r_shadow_shadowmapvsdct;
5283 extern qboolean r_shadow_shadowmapsampler;
5284 extern int r_shadow_shadowmappcf;
5285 extern rtexture_t *r_shadow_shadowmaprectangletexture;
5286 extern rtexture_t *r_shadow_shadowmap2dtexture;
5287 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
5288 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5289 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5290 extern matrix4x4_t r_shadow_shadowmapmatrix;
5291 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5292 extern int r_shadow_prepass_width;
5293 extern int r_shadow_prepass_height;
5294 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5295 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5296 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5297 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5298 extern cvar_t gl_mesh_separatearrays;
5299 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5300 {
5301         // a blendfunc allows colormod if:
5302         // a) it can never keep the destination pixel invariant, or
5303         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5304         // this is to prevent unintended side effects from colormod
5305
5306         // in formulas:
5307         // IF there is a (s, sa) for which for all (d, da),
5308         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5309         // THEN, for this (s, sa) and all (colormod, d, da):
5310         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5311         // OBVIOUSLY, this means that
5312         //   s*colormod * src(s*colormod, d, sa, da) = 0
5313         //   dst(s*colormod, d, sa, da)              = 1
5314
5315         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5316
5317         // main condition to leave dst color invariant:
5318         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5319         //   src == GL_ZERO:
5320         //     s * 0 + d * dst(s, d, sa, da) == d
5321         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5322         //       => colormod is a problem for GL_SRC_COLOR only
5323         //   src == GL_ONE:
5324         //     s + d * dst(s, d, sa, da) == d
5325         //       => s == 0
5326         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5327         //       => colormod is never problematic for these
5328         //   src == GL_SRC_COLOR:
5329         //     s*s + d * dst(s, d, sa, da) == d
5330         //       => s == 0
5331         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5332         //       => colormod is never problematic for these
5333         //   src == GL_ONE_MINUS_SRC_COLOR:
5334         //     s*(1-s) + d * dst(s, d, sa, da) == d
5335         //       => s == 0 or s == 1
5336         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5337         //       => colormod is a problem for GL_SRC_COLOR only
5338         //   src == GL_DST_COLOR
5339         //     s*d + d * dst(s, d, sa, da) == d
5340         //       => s == 1
5341         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5342         //       => colormod is always a problem
5343         //     or
5344         //       => s == 0
5345         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5346         //       => colormod is never problematic for these
5347         //       => BUT, we do not know s! We must assume it is problematic
5348         //       then... except in GL_ONE case, where we know all invariant
5349         //       cases are fine
5350         //   src == GL_ONE_MINUS_DST_COLOR
5351         //     s*(1-d) + d * dst(s, d, sa, da) == d
5352         //       => s == 0 (1-d is impossible to handle for our desired result)
5353         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5354         //       => colormod is never problematic for these
5355         //   src == GL_SRC_ALPHA
5356         //     s*sa + d * dst(s, d, sa, da) == d
5357         //       => s == 0, or sa == 0
5358         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5359         //       => colormod breaks in the case GL_SRC_COLOR only
5360         //   src == GL_ONE_MINUS_SRC_ALPHA
5361         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5362         //       => s == 0, or sa == 1
5363         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5364         //       => colormod breaks in the case GL_SRC_COLOR only
5365         //   src == GL_DST_ALPHA
5366         //     s*da + d * dst(s, d, sa, da) == d
5367         //       => s == 0
5368         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5369         //       => colormod is never problematic for these
5370
5371         switch(src)
5372         {
5373                 case GL_ZERO:
5374                 case GL_ONE_MINUS_SRC_COLOR:
5375                 case GL_SRC_ALPHA:
5376                 case GL_ONE_MINUS_SRC_ALPHA:
5377                         if(dst == GL_SRC_COLOR)
5378                                 return false;
5379                         return true;
5380                 case GL_ONE:
5381                 case GL_SRC_COLOR:
5382                 case GL_ONE_MINUS_DST_COLOR:
5383                 case GL_DST_ALPHA:
5384                 case GL_ONE_MINUS_DST_ALPHA:
5385                         return true;
5386                 case GL_DST_COLOR:
5387                         if(dst == GL_ONE)
5388                                 return true;
5389                         return false;
5390                 default:
5391                         return false;
5392         }
5393 }
5394 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)
5395 {
5396         // select a permutation of the lighting shader appropriate to this
5397         // combination of texture, entity, light source, and fogging, only use the
5398         // minimum features necessary to avoid wasting rendering time in the
5399         // fragment shader on features that are not being used
5400         unsigned int permutation = 0;
5401         unsigned int mode = 0;
5402         qboolean allow_colormod;
5403         static float dummy_colormod[3] = {1, 1, 1};
5404         float *colormod = rsurface.colormod;
5405         float m16f[16];
5406         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5407         if (rsurfacepass == RSURFPASS_BACKGROUND)
5408         {
5409                 // distorted background
5410                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5411                         mode = SHADERMODE_WATER;
5412                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5413                         mode = SHADERMODE_REFRACTION;
5414                 else
5415                 {
5416                         mode = SHADERMODE_GENERIC;
5417                         permutation |= SHADERPERMUTATION_DIFFUSE;
5418                 }
5419                 GL_AlphaTest(false);
5420                 GL_BlendFunc(GL_ONE, GL_ZERO);
5421                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5422         }
5423         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5424         {
5425                 if (r_glsl_offsetmapping.integer)
5426                 {
5427                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5428                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5429                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5430                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5431                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5432                         {
5433                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5434                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5435                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5436                         }
5437                 }
5438                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5439                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5441                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5442                 // normalmap (deferred prepass), may use alpha test on diffuse
5443                 mode = SHADERMODE_DEFERREDGEOMETRY;
5444                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5445                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5446                 GL_AlphaTest(false);
5447                 GL_BlendFunc(GL_ONE, GL_ZERO);
5448                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5449         }
5450         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5451         {
5452                 if (r_glsl_offsetmapping.integer)
5453                 {
5454                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5455                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5456                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5457                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5458                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5459                         {
5460                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5461                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5462                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5463                         }
5464                 }
5465                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5466                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5467                 // light source
5468                 mode = SHADERMODE_LIGHTSOURCE;
5469                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5470                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5471                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5472                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5473                 if (diffusescale > 0)
5474                         permutation |= SHADERPERMUTATION_DIFFUSE;
5475                 if (specularscale > 0)
5476                 {
5477                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5478                         if (r_shadow_glossexact.integer)
5479                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5480                 }
5481                 if (r_refdef.fogenabled)
5482                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5483                 if (rsurface.texture->colormapping)
5484                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5485                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5486                 {
5487                         if (r_shadow_usingshadowmaprect)
5488                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5489                         if (r_shadow_usingshadowmap2d)
5490                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5491                         if (r_shadow_usingshadowmapcube)
5492                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5493                         else if(r_shadow_shadowmapvsdct)
5494                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5495
5496                         if (r_shadow_shadowmapsampler)
5497                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5498                         if (r_shadow_shadowmappcf > 1)
5499                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5500                         else if (r_shadow_shadowmappcf)
5501                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5502                 }
5503                 if (rsurface.texture->reflectmasktexture)
5504                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5505                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5506                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5507                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5508         }
5509         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5510         {
5511                 if (r_glsl_offsetmapping.integer)
5512                 {
5513                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5514                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5515                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5516                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5517                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5518                         {
5519                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5520                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5521                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5522                         }
5523                 }
5524                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5525                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5526                 // unshaded geometry (fullbright or ambient model lighting)
5527                 mode = SHADERMODE_FLATCOLOR;
5528                 ambientscale = diffusescale = specularscale = 0;
5529                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5530                         permutation |= SHADERPERMUTATION_GLOW;
5531                 if (r_refdef.fogenabled)
5532                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5533                 if (rsurface.texture->colormapping)
5534                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5535                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5536                 {
5537                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5538                         if (r_shadow_usingshadowmaprect)
5539                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5540                         if (r_shadow_usingshadowmap2d)
5541                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5542
5543                         if (r_shadow_shadowmapsampler)
5544                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5545                         if (r_shadow_shadowmappcf > 1)
5546                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5547                         else if (r_shadow_shadowmappcf)
5548                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5549                 }
5550                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5551                         permutation |= SHADERPERMUTATION_REFLECTION;
5552                 if (rsurface.texture->reflectmasktexture)
5553                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5554                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5555                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5556                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5557         }
5558         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5559         {
5560                 if (r_glsl_offsetmapping.integer)
5561                 {
5562                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5563                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5564                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5565                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5566                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5567                         {
5568                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5569                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5570                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5571                         }
5572                 }
5573                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5574                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5575                 // directional model lighting
5576                 mode = SHADERMODE_LIGHTDIRECTION;
5577                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5578                         permutation |= SHADERPERMUTATION_GLOW;
5579                 permutation |= SHADERPERMUTATION_DIFFUSE;
5580                 if (specularscale > 0)
5581                 {
5582                         permutation |= SHADERPERMUTATION_SPECULAR;
5583                         if (r_shadow_glossexact.integer)
5584                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5585                 }
5586                 if (r_refdef.fogenabled)
5587                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5588                 if (rsurface.texture->colormapping)
5589                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5590                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5591                 {
5592                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5593                         if (r_shadow_usingshadowmaprect)
5594                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5595                         if (r_shadow_usingshadowmap2d)
5596                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5597
5598                         if (r_shadow_shadowmapsampler)
5599                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5600                         if (r_shadow_shadowmappcf > 1)
5601                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5602                         else if (r_shadow_shadowmappcf)
5603                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5604                 }
5605                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5606                         permutation |= SHADERPERMUTATION_REFLECTION;
5607                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5608                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5609                 if (rsurface.texture->reflectmasktexture)
5610                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5611                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5612                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5613                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5614         }
5615         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5616         {
5617                 if (r_glsl_offsetmapping.integer)
5618                 {
5619                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5620                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5621                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5622                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5623                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5624                         {
5625                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5626                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5627                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5628                         }
5629                 }
5630                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5631                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5632                 // ambient model lighting
5633                 mode = SHADERMODE_LIGHTDIRECTION;
5634                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5635                         permutation |= SHADERPERMUTATION_GLOW;
5636                 if (r_refdef.fogenabled)
5637                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5638                 if (rsurface.texture->colormapping)
5639                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5640                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5641                 {
5642                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5643                         if (r_shadow_usingshadowmaprect)
5644                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5645                         if (r_shadow_usingshadowmap2d)
5646                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5647
5648                         if (r_shadow_shadowmapsampler)
5649                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5650                         if (r_shadow_shadowmappcf > 1)
5651                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5652                         else if (r_shadow_shadowmappcf)
5653                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5654                 }
5655                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5656                         permutation |= SHADERPERMUTATION_REFLECTION;
5657                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5658                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5659                 if (rsurface.texture->reflectmasktexture)
5660                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5661                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5662                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5663                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5664         }
5665         else
5666         {
5667                 if (r_glsl_offsetmapping.integer)
5668                 {
5669                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5670                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5671                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5672                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5673                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5674                         {
5675                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5676                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5677                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5678                         }
5679                 }
5680                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5681                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5682                 // lightmapped wall
5683                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5684                         permutation |= SHADERPERMUTATION_GLOW;
5685                 if (r_refdef.fogenabled)
5686                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5687                 if (rsurface.texture->colormapping)
5688                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5689                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5690                 {
5691                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5692                         if (r_shadow_usingshadowmaprect)
5693                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5694                         if (r_shadow_usingshadowmap2d)
5695                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5696
5697                         if (r_shadow_shadowmapsampler)
5698                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5699                         if (r_shadow_shadowmappcf > 1)
5700                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5701                         else if (r_shadow_shadowmappcf)
5702                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5703                 }
5704                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5705                         permutation |= SHADERPERMUTATION_REFLECTION;
5706                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5707                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5708                 if (rsurface.texture->reflectmasktexture)
5709                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5710                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5711                 {
5712                         // deluxemapping (light direction texture)
5713                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5714                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5715                         else
5716                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5717                         permutation |= SHADERPERMUTATION_DIFFUSE;
5718                         if (specularscale > 0)
5719                         {
5720                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5721                                 if (r_shadow_glossexact.integer)
5722                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5723                         }
5724                 }
5725                 else if (r_glsl_deluxemapping.integer >= 2)
5726                 {
5727                         // fake deluxemapping (uniform light direction in tangentspace)
5728                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5729                         permutation |= SHADERPERMUTATION_DIFFUSE;
5730                         if (specularscale > 0)
5731                         {
5732                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5733                                 if (r_shadow_glossexact.integer)
5734                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5735                         }
5736                 }
5737                 else if (rsurface.uselightmaptexture)
5738                 {
5739                         // ordinary lightmapping (q1bsp, q3bsp)
5740                         mode = SHADERMODE_LIGHTMAP;
5741                 }
5742                 else
5743                 {
5744                         // ordinary vertex coloring (q3bsp)
5745                         mode = SHADERMODE_VERTEXCOLOR;
5746                 }
5747                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5748                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5749                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5750         }
5751         if(!allow_colormod)
5752                 colormod = dummy_colormod;
5753         switch(vid.renderpath)
5754         {
5755         case RENDERPATH_D3D9:
5756 #ifdef SUPPORTD3D
5757                 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);
5758                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5759                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5760                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5761                 if (mode == SHADERMODE_LIGHTSOURCE)
5762                 {
5763                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5764                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5765                 }
5766                 else
5767                 {
5768                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5769                         {
5770                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5771                         }
5772                 }
5773                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5774                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5775                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5776                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5777                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5778
5779                 if (mode == SHADERMODE_LIGHTSOURCE)
5780                 {
5781                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5782                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5783                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5784                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5785                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5786
5787                         // additive passes are only darkened by fog, not tinted
5788                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5789                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5790                 }
5791                 else
5792                 {
5793                         if (mode == SHADERMODE_FLATCOLOR)
5794                         {
5795                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5796                         }
5797                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5798                         {
5799                                 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]);
5800                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5801                                 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);
5802                                 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);
5803                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5804                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5805                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5806                         }
5807                         else
5808                         {
5809                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5810                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5811                                 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);
5812                                 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);
5813                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5814                         }
5815                         // additive passes are only darkened by fog, not tinted
5816                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5817                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5818                         else
5819                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5820                         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);
5821                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5822                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5823                         hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5824                         hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5825                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5826                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5827                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5828                 }
5829                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5830                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5831                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5832                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5833                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5834                 if (rsurface.texture->pantstexture)
5835                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5836                 else
5837                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5838                 if (rsurface.texture->shirttexture)
5839                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5840                 else
5841                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5842                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5843                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5844                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5845                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5846                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5847                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5848                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5849
5850                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5851                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5852                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5853                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5854                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5855                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5856                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5857                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5858                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5859                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5860                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5861                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5862                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5863                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5864                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5865                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5866                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5867                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5868                 {
5869                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5870                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5871                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5872                 }
5873                 else
5874                 {
5875                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5876                 }
5877 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5878 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5879                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5880                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5881                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5882                 {
5883                         R_Mesh_TexBind((permutation & SHADERPERMUTATION_SHADOWMAPORTHO) ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, (permutation & SHADERPERMUTATION_SHADOWSAMPLER) ? r_shadow_shadowmap2dtexture : r_shadow_shadowmap2dcolortexture);
5884                         if (rsurface.rtlight)
5885                         {
5886                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5887                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5888                         }
5889                 }
5890 #endif
5891                 break;
5892         case RENDERPATH_D3D10:
5893                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5894                 break;
5895         case RENDERPATH_D3D11:
5896                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5897                 break;
5898         case RENDERPATH_GL20:
5899                 if (gl_mesh_separatearrays.integer)
5900                 {
5901                         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);
5902                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5903                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5904                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5905                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5906                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5907                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5908                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5909                 }
5910                 else
5911                 {
5912                         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);
5913                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5914                 }
5915                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5916                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5917                 if (mode == SHADERMODE_LIGHTSOURCE)
5918                 {
5919                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5920                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5921                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5922                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5923                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5924                         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);
5925         
5926                         // additive passes are only darkened by fog, not tinted
5927                         if (r_glsl_permutation->loc_FogColor >= 0)
5928                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5929                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5930                 }
5931                 else
5932                 {
5933                         if (mode == SHADERMODE_FLATCOLOR)
5934                         {
5935                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5936                         }
5937                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5938                         {
5939                                 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]);
5940                                 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]);
5941                                 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);
5942                                 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);
5943                                 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);
5944                                 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]);
5945                                 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]);
5946                         }
5947                         else
5948                         {
5949                                 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]);
5950                                 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]);
5951                                 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);
5952                                 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);
5953                                 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);
5954                         }
5955                         // additive passes are only darkened by fog, not tinted
5956                         if (r_glsl_permutation->loc_FogColor >= 0)
5957                         {
5958                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5959                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5960                                 else
5961                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5962                         }
5963                         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);
5964                         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]);
5965                         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]);
5966                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5967                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5968                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5969                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5970                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5971                 }
5972                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5973                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5974                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5975                 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]);
5976                 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]);
5977
5978                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5979                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5980                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5981                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5982                 {
5983                         if (rsurface.texture->pantstexture)
5984                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5985                         else
5986                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5987                 }
5988                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5989                 {
5990                         if (rsurface.texture->shirttexture)
5991                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5992                         else
5993                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5994                 }
5995                 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]);
5996                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5997                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5998                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5999                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6000                 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]);
6001                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6002
6003         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
6004         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
6005         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
6006                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
6007                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
6008                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
6009                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
6010                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
6011                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
6012                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
6013                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
6014                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
6015                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
6016                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
6017                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6018                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
6019                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
6020                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6021                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6022                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
6023                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6024                 {
6025                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6026                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6027                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6028                 }
6029                 else
6030                 {
6031                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6032                 }
6033 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6034 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6035                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6036                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6037                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6038                 {
6039                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6040                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
6041                         if (rsurface.rtlight)
6042                         {
6043                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6044                                 if (r_shadow_usingshadowmapcube)
6045                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6046                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6047                         }
6048                 }
6049                 CHECKGLERROR
6050                 break;
6051         case RENDERPATH_CGGL:
6052 #ifdef SUPPORTCG
6053                 if (gl_mesh_separatearrays.integer)
6054                 {
6055                         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);
6056                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6057                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6058                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6059                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6060                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6061                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6062                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6063                 }
6064                 else
6065                 {
6066                         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);
6067                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6068                 }
6069                 R_SetupShader_SetPermutationCG(mode, permutation);
6070                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6071                 if (mode == SHADERMODE_LIGHTSOURCE)
6072                 {
6073                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6074                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6075                 }
6076                 else
6077                 {
6078                         if (mode == SHADERMODE_LIGHTDIRECTION)
6079                         {
6080                                 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
6081                         }
6082                 }
6083                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6084                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6085                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6086                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6087                 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
6088                 CHECKGLERROR
6089
6090                 if (mode == SHADERMODE_LIGHTSOURCE)
6091                 {
6092                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6093                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6094                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6095                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6096                         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
6097
6098                         // additive passes are only darkened by fog, not tinted
6099                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6100                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6101                 }
6102                 else
6103                 {
6104                         if (mode == SHADERMODE_FLATCOLOR)
6105                         {
6106                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6107                         }
6108                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6109                         {
6110                                 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
6111                                 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
6112                                 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
6113                                 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
6114                                 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
6115                                 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
6116                                 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
6117                         }
6118                         else
6119                         {
6120                                 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
6121                                 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
6122                                 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
6123                                 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
6124                                 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
6125                         }
6126                         // additive passes are only darkened by fog, not tinted
6127                         if (r_cg_permutation->fp_FogColor)
6128                         {
6129                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6130                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6131                                 else
6132                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6133                                 CHECKCGERROR
6134                         }
6135                         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
6136                         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
6137                         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
6138                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
6139                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
6140                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6141                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6142                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6143                 }
6144                 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
6145                 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
6146                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6147                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6148                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6149                 if (r_cg_permutation->fp_Color_Pants)
6150                 {
6151                         if (rsurface.texture->pantstexture)
6152                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6153                         else
6154                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6155                         CHECKCGERROR
6156                 }
6157                 if (r_cg_permutation->fp_Color_Shirt)
6158                 {
6159                         if (rsurface.texture->shirttexture)
6160                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6161                         else
6162                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6163                         CHECKCGERROR
6164                 }
6165                 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
6166                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6167                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6168                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6169                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6170                 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
6171                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6172
6173         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6174         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6175         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6176                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6177                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6178                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6179                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6180                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6181                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6182                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6183                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6184                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6185                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6186                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6187                 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
6188                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6189                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6190                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6191                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6192                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6193                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6194                 {
6195                         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
6196                         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
6197                         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
6198                 }
6199                 else
6200                 {
6201                         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
6202                 }
6203                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6204                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6205                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6206                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6207                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6208                 {
6209                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6210                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
6211                         if (rsurface.rtlight)
6212                         {
6213                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6214                                 if (r_shadow_usingshadowmapcube)
6215                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6216                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6217                         }
6218                 }
6219
6220                 CHECKGLERROR
6221 #endif
6222                 break;
6223         case RENDERPATH_GL13:
6224         case RENDERPATH_GL11:
6225                 break;
6226         }
6227 }
6228
6229 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6230 {
6231         // select a permutation of the lighting shader appropriate to this
6232         // combination of texture, entity, light source, and fogging, only use the
6233         // minimum features necessary to avoid wasting rendering time in the
6234         // fragment shader on features that are not being used
6235         unsigned int permutation = 0;
6236         unsigned int mode = 0;
6237         const float *lightcolorbase = rtlight->currentcolor;
6238         float ambientscale = rtlight->ambientscale;
6239         float diffusescale = rtlight->diffusescale;
6240         float specularscale = rtlight->specularscale;
6241         // this is the location of the light in view space
6242         vec3_t viewlightorigin;
6243         // this transforms from view space (camera) to light space (cubemap)
6244         matrix4x4_t viewtolight;
6245         matrix4x4_t lighttoview;
6246         float viewtolight16f[16];
6247         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6248         // light source
6249         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6250         if (rtlight->currentcubemap != r_texture_whitecube)
6251                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6252         if (diffusescale > 0)
6253                 permutation |= SHADERPERMUTATION_DIFFUSE;
6254         if (specularscale > 0)
6255         {
6256                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6257                 if (r_shadow_glossexact.integer)
6258                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6259         }
6260         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
6261         {
6262                 if (r_shadow_usingshadowmaprect)
6263                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
6264                 if (r_shadow_usingshadowmap2d)
6265                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6266                 if (r_shadow_usingshadowmapcube)
6267                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
6268                 else if(r_shadow_shadowmapvsdct)
6269                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6270
6271                 if (r_shadow_shadowmapsampler)
6272                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6273                 if (r_shadow_shadowmappcf > 1)
6274                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6275                 else if (r_shadow_shadowmappcf)
6276                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6277         }
6278         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6279         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6280         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6281         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6282         switch(vid.renderpath)
6283         {
6284         case RENDERPATH_D3D9:
6285 #ifdef SUPPORTD3D
6286                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6287                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6288                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6289                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6290                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6291                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6292                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6293                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6294                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6295                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6296                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6297
6298                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6299                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6300                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6301                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6302                 R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
6303                 if (r_shadow_usingshadowmapcube)
6304                         R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6305                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6306                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6307 #endif
6308                 break;
6309         case RENDERPATH_D3D10:
6310                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6311                 break;
6312         case RENDERPATH_D3D11:
6313                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6314                 break;
6315         case RENDERPATH_GL20:
6316                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6317                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6318                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6319                 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);
6320                 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);
6321                 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);
6322                 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]);
6323                 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]);
6324                 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));
6325                 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]);
6326                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6327
6328                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6329                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6330                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6331                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6332                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
6333                 if (r_shadow_usingshadowmapcube)
6334                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6335                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6336                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6337                 break;
6338         case RENDERPATH_CGGL:
6339 #ifdef SUPPORTCG
6340                 R_SetupShader_SetPermutationCG(mode, permutation);
6341                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6342                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6343                 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
6344                 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
6345                 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
6346                 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
6347                 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
6348                 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
6349                 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
6350                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6351
6352                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6353                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6354                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6355                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6356                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
6357                 if (r_shadow_usingshadowmapcube)
6358                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6359                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6360                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6361 #endif
6362                 break;
6363         case RENDERPATH_GL13:
6364         case RENDERPATH_GL11:
6365                 break;
6366         }
6367 }
6368
6369 #define SKINFRAME_HASH 1024
6370
6371 typedef struct
6372 {
6373         int loadsequence; // incremented each level change
6374         memexpandablearray_t array;
6375         skinframe_t *hash[SKINFRAME_HASH];
6376 }
6377 r_skinframe_t;
6378 r_skinframe_t r_skinframe;
6379
6380 void R_SkinFrame_PrepareForPurge(void)
6381 {
6382         r_skinframe.loadsequence++;
6383         // wrap it without hitting zero
6384         if (r_skinframe.loadsequence >= 200)
6385                 r_skinframe.loadsequence = 1;
6386 }
6387
6388 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6389 {
6390         if (!skinframe)
6391                 return;
6392         // mark the skinframe as used for the purging code
6393         skinframe->loadsequence = r_skinframe.loadsequence;
6394 }
6395
6396 void R_SkinFrame_Purge(void)
6397 {
6398         int i;
6399         skinframe_t *s;
6400         for (i = 0;i < SKINFRAME_HASH;i++)
6401         {
6402                 for (s = r_skinframe.hash[i];s;s = s->next)
6403                 {
6404                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6405                         {
6406                                 if (s->merged == s->base)
6407                                         s->merged = NULL;
6408                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6409                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6410                                 R_PurgeTexture(s->merged);s->merged = NULL;
6411                                 R_PurgeTexture(s->base  );s->base   = NULL;
6412                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6413                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6414                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6415                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6416                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6417                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6418                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6419                                 s->loadsequence = 0;
6420                         }
6421                 }
6422         }
6423 }
6424
6425 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6426         skinframe_t *item;
6427         char basename[MAX_QPATH];
6428
6429         Image_StripImageExtension(name, basename, sizeof(basename));
6430
6431         if( last == NULL ) {
6432                 int hashindex;
6433                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6434                 item = r_skinframe.hash[hashindex];
6435         } else {
6436                 item = last->next;
6437         }
6438
6439         // linearly search through the hash bucket
6440         for( ; item ; item = item->next ) {
6441                 if( !strcmp( item->basename, basename ) ) {
6442                         return item;
6443                 }
6444         }
6445         return NULL;
6446 }
6447
6448 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6449 {
6450         skinframe_t *item;
6451         int hashindex;
6452         char basename[MAX_QPATH];
6453
6454         Image_StripImageExtension(name, basename, sizeof(basename));
6455
6456         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6457         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6458                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6459                         break;
6460
6461         if (!item) {
6462                 rtexture_t *dyntexture;
6463                 // check whether its a dynamic texture
6464                 dyntexture = CL_GetDynTexture( basename );
6465                 if (!add && !dyntexture)
6466                         return NULL;
6467                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6468                 memset(item, 0, sizeof(*item));
6469                 strlcpy(item->basename, basename, sizeof(item->basename));
6470                 item->base = dyntexture; // either NULL or dyntexture handle
6471                 item->textureflags = textureflags;
6472                 item->comparewidth = comparewidth;
6473                 item->compareheight = compareheight;
6474                 item->comparecrc = comparecrc;
6475                 item->next = r_skinframe.hash[hashindex];
6476                 r_skinframe.hash[hashindex] = item;
6477         }
6478         else if( item->base == NULL )
6479         {
6480                 rtexture_t *dyntexture;
6481                 // check whether its a dynamic texture
6482                 // 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]
6483                 dyntexture = CL_GetDynTexture( basename );
6484                 item->base = dyntexture; // either NULL or dyntexture handle
6485         }
6486
6487         R_SkinFrame_MarkUsed(item);
6488         return item;
6489 }
6490
6491 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6492         { \
6493                 unsigned long long avgcolor[5], wsum; \
6494                 int pix, comp, w; \
6495                 avgcolor[0] = 0; \
6496                 avgcolor[1] = 0; \
6497                 avgcolor[2] = 0; \
6498                 avgcolor[3] = 0; \
6499                 avgcolor[4] = 0; \
6500                 wsum = 0; \
6501                 for(pix = 0; pix < cnt; ++pix) \
6502                 { \
6503                         w = 0; \
6504                         for(comp = 0; comp < 3; ++comp) \
6505                                 w += getpixel; \
6506                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6507                         { \
6508                                 ++wsum; \
6509                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6510                                 w = getpixel; \
6511                                 for(comp = 0; comp < 3; ++comp) \
6512                                         avgcolor[comp] += getpixel * w; \
6513                                 avgcolor[3] += w; \
6514                         } \
6515                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6516                         avgcolor[4] += getpixel; \
6517                 } \
6518                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6519                         avgcolor[3] = 1; \
6520                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6521                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6522                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6523                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6524         }
6525
6526 extern cvar_t gl_picmip;
6527 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6528 {
6529         int j;
6530         unsigned char *pixels;
6531         unsigned char *bumppixels;
6532         unsigned char *basepixels = NULL;
6533         int basepixels_width = 0;
6534         int basepixels_height = 0;
6535         skinframe_t *skinframe;
6536         rtexture_t *ddsbase = NULL;
6537         qboolean ddshasalpha = false;
6538         float ddsavgcolor[4];
6539         char basename[MAX_QPATH];
6540         int miplevel = R_PicmipForFlags(textureflags);
6541         int savemiplevel = miplevel;
6542         int mymiplevel;
6543
6544         if (cls.state == ca_dedicated)
6545                 return NULL;
6546
6547         // return an existing skinframe if already loaded
6548         // if loading of the first image fails, don't make a new skinframe as it
6549         // would cause all future lookups of this to be missing
6550         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6551         if (skinframe && skinframe->base)
6552                 return skinframe;
6553
6554         Image_StripImageExtension(name, basename, sizeof(basename));
6555
6556         // check for DDS texture file first
6557         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6558         {
6559                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6560                 if (basepixels == NULL)
6561                         return NULL;
6562         }
6563
6564         // FIXME handle miplevel
6565
6566         if (developer_loading.integer)
6567                 Con_Printf("loading skin \"%s\"\n", name);
6568
6569         // we've got some pixels to store, so really allocate this new texture now
6570         if (!skinframe)
6571                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6572         skinframe->stain = NULL;
6573         skinframe->merged = NULL;
6574         skinframe->base = NULL;
6575         skinframe->pants = NULL;
6576         skinframe->shirt = NULL;
6577         skinframe->nmap = NULL;
6578         skinframe->gloss = NULL;
6579         skinframe->glow = NULL;
6580         skinframe->fog = NULL;
6581         skinframe->reflect = NULL;
6582         skinframe->hasalpha = false;
6583
6584         if (ddsbase)
6585         {
6586                 skinframe->base = ddsbase;
6587                 skinframe->hasalpha = ddshasalpha;
6588                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6589                 if (r_loadfog && skinframe->hasalpha)
6590                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6591                 //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]);
6592         }
6593         else
6594         {
6595                 basepixels_width = image_width;
6596                 basepixels_height = image_height;
6597                 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);
6598                 if (textureflags & TEXF_ALPHA)
6599                 {
6600                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6601                         {
6602                                 if (basepixels[j] < 255)
6603                                 {
6604                                         skinframe->hasalpha = true;
6605                                         break;
6606                                 }
6607                         }
6608                         if (r_loadfog && skinframe->hasalpha)
6609                         {
6610                                 // has transparent pixels
6611                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6612                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6613                                 {
6614                                         pixels[j+0] = 255;
6615                                         pixels[j+1] = 255;
6616                                         pixels[j+2] = 255;
6617                                         pixels[j+3] = basepixels[j+3];
6618                                 }
6619                                 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);
6620                                 Mem_Free(pixels);
6621                         }
6622                 }
6623                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6624                 //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]);
6625                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6626                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6627                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6628                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6629         }
6630
6631         if (r_loaddds)
6632         {
6633                 mymiplevel = savemiplevel;
6634                 if (r_loadnormalmap)
6635                         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);
6636                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6637                 if (r_loadgloss)
6638                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6639                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6640                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6641                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6642         }
6643
6644         // _norm is the name used by tenebrae and has been adopted as standard
6645         if (r_loadnormalmap && skinframe->nmap == NULL)
6646         {
6647                 mymiplevel = savemiplevel;
6648                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6649                 {
6650                         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);
6651                         Mem_Free(pixels);
6652                         pixels = NULL;
6653                 }
6654                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6655                 {
6656                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6657                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6658                         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);
6659                         Mem_Free(pixels);
6660                         Mem_Free(bumppixels);
6661                 }
6662                 else if (r_shadow_bumpscale_basetexture.value > 0)
6663                 {
6664                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6665                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6666                         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);
6667                         Mem_Free(pixels);
6668                 }
6669                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6670                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6671         }
6672
6673         // _luma is supported only for tenebrae compatibility
6674         // _glow is the preferred name
6675         mymiplevel = savemiplevel;
6676         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))))
6677         {
6678                 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);
6679                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6680                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6681                 Mem_Free(pixels);pixels = NULL;
6682         }
6683
6684         mymiplevel = savemiplevel;
6685         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6686         {
6687                 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);
6688                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6689                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6690                 Mem_Free(pixels);
6691                 pixels = NULL;
6692         }
6693
6694         mymiplevel = savemiplevel;
6695         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6696         {
6697                 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);
6698                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6699                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6700                 Mem_Free(pixels);
6701                 pixels = NULL;
6702         }
6703
6704         mymiplevel = savemiplevel;
6705         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6706         {
6707                 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);
6708                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6709                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6710                 Mem_Free(pixels);
6711                 pixels = NULL;
6712         }
6713
6714         mymiplevel = savemiplevel;
6715         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6716         {
6717                 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);
6718                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6719                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6720                 Mem_Free(pixels);
6721                 pixels = NULL;
6722         }
6723
6724         if (basepixels)
6725                 Mem_Free(basepixels);
6726
6727         return skinframe;
6728 }
6729
6730 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6731 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6732 {
6733         int i;
6734         unsigned char *temp1, *temp2;
6735         skinframe_t *skinframe;
6736
6737         if (cls.state == ca_dedicated)
6738                 return NULL;
6739
6740         // if already loaded just return it, otherwise make a new skinframe
6741         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6742         if (skinframe && skinframe->base)
6743                 return skinframe;
6744
6745         skinframe->stain = NULL;
6746         skinframe->merged = NULL;
6747         skinframe->base = NULL;
6748         skinframe->pants = NULL;
6749         skinframe->shirt = NULL;
6750         skinframe->nmap = NULL;
6751         skinframe->gloss = NULL;
6752         skinframe->glow = NULL;
6753         skinframe->fog = NULL;
6754         skinframe->reflect = NULL;
6755         skinframe->hasalpha = false;
6756
6757         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6758         if (!skindata)
6759                 return NULL;
6760
6761         if (developer_loading.integer)
6762                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6763
6764         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6765         {
6766                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6767                 temp2 = temp1 + width * height * 4;
6768                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6769                 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);
6770                 Mem_Free(temp1);
6771         }
6772         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6773         if (textureflags & TEXF_ALPHA)
6774         {
6775                 for (i = 3;i < width * height * 4;i += 4)
6776                 {
6777                         if (skindata[i] < 255)
6778                         {
6779                                 skinframe->hasalpha = true;
6780                                 break;
6781                         }
6782                 }
6783                 if (r_loadfog && skinframe->hasalpha)
6784                 {
6785                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6786                         memcpy(fogpixels, skindata, width * height * 4);
6787                         for (i = 0;i < width * height * 4;i += 4)
6788                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6789                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6790                         Mem_Free(fogpixels);
6791                 }
6792         }
6793
6794         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6795         //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]);
6796
6797         return skinframe;
6798 }
6799
6800 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6801 {
6802         int i;
6803         int featuresmask;
6804         skinframe_t *skinframe;
6805
6806         if (cls.state == ca_dedicated)
6807                 return NULL;
6808
6809         // if already loaded just return it, otherwise make a new skinframe
6810         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6811         if (skinframe && skinframe->base)
6812                 return skinframe;
6813
6814         skinframe->stain = NULL;
6815         skinframe->merged = NULL;
6816         skinframe->base = NULL;
6817         skinframe->pants = NULL;
6818         skinframe->shirt = NULL;
6819         skinframe->nmap = NULL;
6820         skinframe->gloss = NULL;
6821         skinframe->glow = NULL;
6822         skinframe->fog = NULL;
6823         skinframe->reflect = NULL;
6824         skinframe->hasalpha = false;
6825
6826         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6827         if (!skindata)
6828                 return NULL;
6829
6830         if (developer_loading.integer)
6831                 Con_Printf("loading quake skin \"%s\"\n", name);
6832
6833         // 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)
6834         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6835         memcpy(skinframe->qpixels, skindata, width*height);
6836         skinframe->qwidth = width;
6837         skinframe->qheight = height;
6838
6839         featuresmask = 0;
6840         for (i = 0;i < width * height;i++)
6841                 featuresmask |= palette_featureflags[skindata[i]];
6842
6843         skinframe->hasalpha = false;
6844         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6845         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6846         skinframe->qgeneratemerged = true;
6847         skinframe->qgeneratebase = skinframe->qhascolormapping;
6848         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6849
6850         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6851         //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]);
6852
6853         return skinframe;
6854 }
6855
6856 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6857 {
6858         int width;
6859         int height;
6860         unsigned char *skindata;
6861
6862         if (!skinframe->qpixels)
6863                 return;
6864
6865         if (!skinframe->qhascolormapping)
6866                 colormapped = false;
6867
6868         if (colormapped)
6869         {
6870                 if (!skinframe->qgeneratebase)
6871                         return;
6872         }
6873         else
6874         {
6875                 if (!skinframe->qgeneratemerged)
6876                         return;
6877         }
6878
6879         width = skinframe->qwidth;
6880         height = skinframe->qheight;
6881         skindata = skinframe->qpixels;
6882
6883         if (skinframe->qgeneratenmap)
6884         {
6885                 unsigned char *temp1, *temp2;
6886                 skinframe->qgeneratenmap = false;
6887                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6888                 temp2 = temp1 + width * height * 4;
6889                 // use either a custom palette or the quake palette
6890                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6891                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6892                 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);
6893                 Mem_Free(temp1);
6894         }
6895
6896         if (skinframe->qgenerateglow)
6897         {
6898                 skinframe->qgenerateglow = false;
6899                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6900         }
6901
6902         if (colormapped)
6903         {
6904                 skinframe->qgeneratebase = false;
6905                 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);
6906                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6907                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6908         }
6909         else
6910         {
6911                 skinframe->qgeneratemerged = false;
6912                 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);
6913         }
6914
6915         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6916         {
6917                 Mem_Free(skinframe->qpixels);
6918                 skinframe->qpixels = NULL;
6919         }
6920 }
6921
6922 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)
6923 {
6924         int i;
6925         skinframe_t *skinframe;
6926
6927         if (cls.state == ca_dedicated)
6928                 return NULL;
6929
6930         // if already loaded just return it, otherwise make a new skinframe
6931         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6932         if (skinframe && skinframe->base)
6933                 return skinframe;
6934
6935         skinframe->stain = NULL;
6936         skinframe->merged = NULL;
6937         skinframe->base = NULL;
6938         skinframe->pants = NULL;
6939         skinframe->shirt = NULL;
6940         skinframe->nmap = NULL;
6941         skinframe->gloss = NULL;
6942         skinframe->glow = NULL;
6943         skinframe->fog = NULL;
6944         skinframe->reflect = NULL;
6945         skinframe->hasalpha = false;
6946
6947         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6948         if (!skindata)
6949                 return NULL;
6950
6951         if (developer_loading.integer)
6952                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6953
6954         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6955         if (textureflags & TEXF_ALPHA)
6956         {
6957                 for (i = 0;i < width * height;i++)
6958                 {
6959                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6960                         {
6961                                 skinframe->hasalpha = true;
6962                                 break;
6963                         }
6964                 }
6965                 if (r_loadfog && skinframe->hasalpha)
6966                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6967         }
6968
6969         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6970         //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]);
6971
6972         return skinframe;
6973 }
6974
6975 skinframe_t *R_SkinFrame_LoadMissing(void)
6976 {
6977         skinframe_t *skinframe;
6978
6979         if (cls.state == ca_dedicated)
6980                 return NULL;
6981
6982         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6983         skinframe->stain = NULL;
6984         skinframe->merged = NULL;
6985         skinframe->base = NULL;
6986         skinframe->pants = NULL;
6987         skinframe->shirt = NULL;
6988         skinframe->nmap = NULL;
6989         skinframe->gloss = NULL;
6990         skinframe->glow = NULL;
6991         skinframe->fog = NULL;
6992         skinframe->reflect = NULL;
6993         skinframe->hasalpha = false;
6994
6995         skinframe->avgcolor[0] = rand() / RAND_MAX;
6996         skinframe->avgcolor[1] = rand() / RAND_MAX;
6997         skinframe->avgcolor[2] = rand() / RAND_MAX;
6998         skinframe->avgcolor[3] = 1;
6999
7000         return skinframe;
7001 }
7002
7003 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7004 typedef struct suffixinfo_s
7005 {
7006         const char *suffix;
7007         qboolean flipx, flipy, flipdiagonal;
7008 }
7009 suffixinfo_t;
7010 static suffixinfo_t suffix[3][6] =
7011 {
7012         {
7013                 {"px",   false, false, false},
7014                 {"nx",   false, false, false},
7015                 {"py",   false, false, false},
7016                 {"ny",   false, false, false},
7017                 {"pz",   false, false, false},
7018                 {"nz",   false, false, false}
7019         },
7020         {
7021                 {"posx", false, false, false},
7022                 {"negx", false, false, false},
7023                 {"posy", false, false, false},
7024                 {"negy", false, false, false},
7025                 {"posz", false, false, false},
7026                 {"negz", false, false, false}
7027         },
7028         {
7029                 {"rt",    true, false,  true},
7030                 {"lf",   false,  true,  true},
7031                 {"ft",    true,  true, false},
7032                 {"bk",   false, false, false},
7033                 {"up",    true, false,  true},
7034                 {"dn",    true, false,  true}
7035         }
7036 };
7037
7038 static int componentorder[4] = {0, 1, 2, 3};
7039
7040 rtexture_t *R_LoadCubemap(const char *basename)
7041 {
7042         int i, j, cubemapsize;
7043         unsigned char *cubemappixels, *image_buffer;
7044         rtexture_t *cubemaptexture;
7045         char name[256];
7046         // must start 0 so the first loadimagepixels has no requested width/height
7047         cubemapsize = 0;
7048         cubemappixels = NULL;
7049         cubemaptexture = NULL;
7050         // keep trying different suffix groups (posx, px, rt) until one loads
7051         for (j = 0;j < 3 && !cubemappixels;j++)
7052         {
7053                 // load the 6 images in the suffix group
7054                 for (i = 0;i < 6;i++)
7055                 {
7056                         // generate an image name based on the base and and suffix
7057                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7058                         // load it
7059                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7060                         {
7061                                 // an image loaded, make sure width and height are equal
7062                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7063                                 {
7064                                         // if this is the first image to load successfully, allocate the cubemap memory
7065                                         if (!cubemappixels && image_width >= 1)
7066                                         {
7067                                                 cubemapsize = image_width;
7068                                                 // note this clears to black, so unavailable sides are black
7069                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7070                                         }
7071                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7072                                         if (cubemappixels)
7073                                                 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);
7074                                 }
7075                                 else
7076                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7077                                 // free the image
7078                                 Mem_Free(image_buffer);
7079                         }
7080                 }
7081         }
7082         // if a cubemap loaded, upload it
7083         if (cubemappixels)
7084         {
7085                 if (developer_loading.integer)
7086                         Con_Printf("loading cubemap \"%s\"\n", basename);
7087
7088                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7089                 Mem_Free(cubemappixels);
7090         }
7091         else
7092         {
7093                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7094                 if (developer_loading.integer)
7095                 {
7096                         Con_Printf("(tried tried images ");
7097                         for (j = 0;j < 3;j++)
7098                                 for (i = 0;i < 6;i++)
7099                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7100                         Con_Print(" and was unable to find any of them).\n");
7101                 }
7102         }
7103         return cubemaptexture;
7104 }
7105
7106 rtexture_t *R_GetCubemap(const char *basename)
7107 {
7108         int i;
7109         for (i = 0;i < r_texture_numcubemaps;i++)
7110                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7111                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7112         if (i >= MAX_CUBEMAPS)
7113                 return r_texture_whitecube;
7114         r_texture_numcubemaps++;
7115         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7116         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7117         return r_texture_cubemaps[i].texture;
7118 }
7119
7120 void R_FreeCubemaps(void)
7121 {
7122         int i;
7123         for (i = 0;i < r_texture_numcubemaps;i++)
7124         {
7125                 if (developer_loading.integer)
7126                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7127                 if (r_texture_cubemaps[i].texture)
7128                         R_FreeTexture(r_texture_cubemaps[i].texture);
7129         }
7130         r_texture_numcubemaps = 0;
7131 }
7132
7133 void R_Main_FreeViewCache(void)
7134 {
7135         if (r_refdef.viewcache.entityvisible)
7136                 Mem_Free(r_refdef.viewcache.entityvisible);
7137         if (r_refdef.viewcache.world_pvsbits)
7138                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7139         if (r_refdef.viewcache.world_leafvisible)
7140                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7141         if (r_refdef.viewcache.world_surfacevisible)
7142                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7143         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7144 }
7145
7146 void R_Main_ResizeViewCache(void)
7147 {
7148         int numentities = r_refdef.scene.numentities;
7149         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7150         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7151         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7152         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7153         if (r_refdef.viewcache.maxentities < numentities)
7154         {
7155                 r_refdef.viewcache.maxentities = numentities;
7156                 if (r_refdef.viewcache.entityvisible)
7157                         Mem_Free(r_refdef.viewcache.entityvisible);
7158                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7159         }
7160         if (r_refdef.viewcache.world_numclusters != numclusters)
7161         {
7162                 r_refdef.viewcache.world_numclusters = numclusters;
7163                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7164                 if (r_refdef.viewcache.world_pvsbits)
7165                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7166                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7167         }
7168         if (r_refdef.viewcache.world_numleafs != numleafs)
7169         {
7170                 r_refdef.viewcache.world_numleafs = numleafs;
7171                 if (r_refdef.viewcache.world_leafvisible)
7172                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7173                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7174         }
7175         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7176         {
7177                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7178                 if (r_refdef.viewcache.world_surfacevisible)
7179                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7180                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7181         }
7182 }
7183
7184 extern rtexture_t *loadingscreentexture;
7185 void gl_main_start(void)
7186 {
7187         loadingscreentexture = NULL;
7188         r_texture_blanknormalmap = NULL;
7189         r_texture_white = NULL;
7190         r_texture_grey128 = NULL;
7191         r_texture_black = NULL;
7192         r_texture_whitecube = NULL;
7193         r_texture_normalizationcube = NULL;
7194         r_texture_fogattenuation = NULL;
7195         r_texture_fogheighttexture = NULL;
7196         r_texture_gammaramps = NULL;
7197         r_texture_numcubemaps = 0;
7198
7199         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7200         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7201
7202         switch(vid.renderpath)
7203         {
7204         case RENDERPATH_GL20:
7205         case RENDERPATH_CGGL:
7206         case RENDERPATH_D3D9:
7207         case RENDERPATH_D3D10:
7208         case RENDERPATH_D3D11:
7209                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7210                 Cvar_SetValueQuick(&gl_combine, 1);
7211                 Cvar_SetValueQuick(&r_glsl, 1);
7212                 r_loadnormalmap = true;
7213                 r_loadgloss = true;
7214                 r_loadfog = false;
7215                 break;
7216         case RENDERPATH_GL13:
7217                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7218                 Cvar_SetValueQuick(&gl_combine, 1);
7219                 Cvar_SetValueQuick(&r_glsl, 0);
7220                 r_loadnormalmap = false;
7221                 r_loadgloss = false;
7222                 r_loadfog = true;
7223                 break;
7224         case RENDERPATH_GL11:
7225                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7226                 Cvar_SetValueQuick(&gl_combine, 0);
7227                 Cvar_SetValueQuick(&r_glsl, 0);
7228                 r_loadnormalmap = false;
7229                 r_loadgloss = false;
7230                 r_loadfog = true;
7231                 break;
7232         }
7233
7234         R_AnimCache_Free();
7235         R_FrameData_Reset();
7236
7237         r_numqueries = 0;
7238         r_maxqueries = 0;
7239         memset(r_queries, 0, sizeof(r_queries));
7240
7241         r_qwskincache = NULL;
7242         r_qwskincache_size = 0;
7243
7244         // set up r_skinframe loading system for textures
7245         memset(&r_skinframe, 0, sizeof(r_skinframe));
7246         r_skinframe.loadsequence = 1;
7247         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7248
7249         r_main_texturepool = R_AllocTexturePool();
7250         R_BuildBlankTextures();
7251         R_BuildNoTexture();
7252         if (vid.support.arb_texture_cube_map)
7253         {
7254                 R_BuildWhiteCube();
7255                 R_BuildNormalizationCube();
7256         }
7257         r_texture_fogattenuation = NULL;
7258         r_texture_fogheighttexture = NULL;
7259         r_texture_gammaramps = NULL;
7260         //r_texture_fogintensity = NULL;
7261         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7262         memset(&r_waterstate, 0, sizeof(r_waterstate));
7263         r_glsl_permutation = NULL;
7264         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7265         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7266         glslshaderstring = NULL;
7267 #ifdef SUPPORTCG
7268         r_cg_permutation = NULL;
7269         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7270         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7271         cgshaderstring = NULL;
7272 #endif
7273 #ifdef SUPPORTD3D
7274         r_hlsl_permutation = NULL;
7275         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7276         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7277         hlslshaderstring = NULL;
7278 #endif
7279         memset(&r_svbsp, 0, sizeof (r_svbsp));
7280
7281         r_refdef.fogmasktable_density = 0;
7282 }
7283
7284 void gl_main_shutdown(void)
7285 {
7286         R_AnimCache_Free();
7287         R_FrameData_Reset();
7288
7289         R_Main_FreeViewCache();
7290
7291         switch(vid.renderpath)
7292         {
7293         case RENDERPATH_GL11:
7294         case RENDERPATH_GL13:
7295         case RENDERPATH_GL20:
7296         case RENDERPATH_CGGL:
7297                 if (r_maxqueries)
7298                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7299                 break;
7300         case RENDERPATH_D3D9:
7301                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7302                 break;
7303         case RENDERPATH_D3D10:
7304                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7305                 break;
7306         case RENDERPATH_D3D11:
7307                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7308                 break;
7309         }
7310
7311         r_numqueries = 0;
7312         r_maxqueries = 0;
7313         memset(r_queries, 0, sizeof(r_queries));
7314
7315         r_qwskincache = NULL;
7316         r_qwskincache_size = 0;
7317
7318         // clear out the r_skinframe state
7319         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7320         memset(&r_skinframe, 0, sizeof(r_skinframe));
7321
7322         if (r_svbsp.nodes)
7323                 Mem_Free(r_svbsp.nodes);
7324         memset(&r_svbsp, 0, sizeof (r_svbsp));
7325         R_FreeTexturePool(&r_main_texturepool);
7326         loadingscreentexture = NULL;
7327         r_texture_blanknormalmap = NULL;
7328         r_texture_white = NULL;
7329         r_texture_grey128 = NULL;
7330         r_texture_black = NULL;
7331         r_texture_whitecube = NULL;
7332         r_texture_normalizationcube = NULL;
7333         r_texture_fogattenuation = NULL;
7334         r_texture_fogheighttexture = NULL;
7335         r_texture_gammaramps = NULL;
7336         r_texture_numcubemaps = 0;
7337         //r_texture_fogintensity = NULL;
7338         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7339         memset(&r_waterstate, 0, sizeof(r_waterstate));
7340         R_GLSL_Restart_f();
7341 }
7342
7343 extern void CL_ParseEntityLump(char *entitystring);
7344 void gl_main_newmap(void)
7345 {
7346         // FIXME: move this code to client
7347         char *entities, entname[MAX_QPATH];
7348         if (r_qwskincache)
7349                 Mem_Free(r_qwskincache);
7350         r_qwskincache = NULL;
7351         r_qwskincache_size = 0;
7352         if (cl.worldmodel)
7353         {
7354                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7355                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7356                 {
7357                         CL_ParseEntityLump(entities);
7358                         Mem_Free(entities);
7359                         return;
7360                 }
7361                 if (cl.worldmodel->brush.entities)
7362                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7363         }
7364         R_Main_FreeViewCache();
7365
7366         R_FrameData_Reset();
7367 }
7368
7369 void GL_Main_Init(void)
7370 {
7371         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7372
7373         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7374         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7375         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7376         if (gamemode == GAME_NEHAHRA)
7377         {
7378                 Cvar_RegisterVariable (&gl_fogenable);
7379                 Cvar_RegisterVariable (&gl_fogdensity);
7380                 Cvar_RegisterVariable (&gl_fogred);
7381                 Cvar_RegisterVariable (&gl_foggreen);
7382                 Cvar_RegisterVariable (&gl_fogblue);
7383                 Cvar_RegisterVariable (&gl_fogstart);
7384                 Cvar_RegisterVariable (&gl_fogend);
7385                 Cvar_RegisterVariable (&gl_skyclip);
7386         }
7387         Cvar_RegisterVariable(&r_motionblur);
7388         Cvar_RegisterVariable(&r_motionblur_maxblur);
7389         Cvar_RegisterVariable(&r_motionblur_bmin);
7390         Cvar_RegisterVariable(&r_motionblur_vmin);
7391         Cvar_RegisterVariable(&r_motionblur_vmax);
7392         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7393         Cvar_RegisterVariable(&r_motionblur_randomize);
7394         Cvar_RegisterVariable(&r_damageblur);
7395         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7396         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7397         Cvar_RegisterVariable(&r_equalize_entities_by);
7398         Cvar_RegisterVariable(&r_equalize_entities_to);
7399         Cvar_RegisterVariable(&r_depthfirst);
7400         Cvar_RegisterVariable(&r_useinfinitefarclip);
7401         Cvar_RegisterVariable(&r_farclip_base);
7402         Cvar_RegisterVariable(&r_farclip_world);
7403         Cvar_RegisterVariable(&r_nearclip);
7404         Cvar_RegisterVariable(&r_showbboxes);
7405         Cvar_RegisterVariable(&r_showsurfaces);
7406         Cvar_RegisterVariable(&r_showtris);
7407         Cvar_RegisterVariable(&r_shownormals);
7408         Cvar_RegisterVariable(&r_showlighting);
7409         Cvar_RegisterVariable(&r_showshadowvolumes);
7410         Cvar_RegisterVariable(&r_showcollisionbrushes);
7411         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7412         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7413         Cvar_RegisterVariable(&r_showdisabledepthtest);
7414         Cvar_RegisterVariable(&r_drawportals);
7415         Cvar_RegisterVariable(&r_drawentities);
7416         Cvar_RegisterVariable(&r_draw2d);
7417         Cvar_RegisterVariable(&r_drawworld);
7418         Cvar_RegisterVariable(&r_cullentities_trace);
7419         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7420         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7421         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7422         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7423         Cvar_RegisterVariable(&r_drawviewmodel);
7424         Cvar_RegisterVariable(&r_drawexteriormodel);
7425         Cvar_RegisterVariable(&r_speeds);
7426         Cvar_RegisterVariable(&r_fullbrights);
7427         Cvar_RegisterVariable(&r_wateralpha);
7428         Cvar_RegisterVariable(&r_dynamic);
7429         Cvar_RegisterVariable(&r_fullbright);
7430         Cvar_RegisterVariable(&r_shadows);
7431         Cvar_RegisterVariable(&r_shadows_darken);
7432         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7433         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7434         Cvar_RegisterVariable(&r_shadows_throwdistance);
7435         Cvar_RegisterVariable(&r_shadows_throwdirection);
7436         Cvar_RegisterVariable(&r_shadows_focus);
7437         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7438         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7439         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7440         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7441         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7442         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7443         Cvar_RegisterVariable(&r_fog_exp2);
7444         Cvar_RegisterVariable(&r_drawfog);
7445         Cvar_RegisterVariable(&r_transparentdepthmasking);
7446         Cvar_RegisterVariable(&r_texture_dds_load);
7447         Cvar_RegisterVariable(&r_texture_dds_save);
7448         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7449         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7450         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7451         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7452         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7453         Cvar_RegisterVariable(&r_textureunits);
7454         Cvar_RegisterVariable(&gl_combine);
7455         Cvar_RegisterVariable(&r_glsl);
7456         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7457         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7458         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7459         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7460         Cvar_RegisterVariable(&r_glsl_postprocess);
7461         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7462         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7463         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7464         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7465         Cvar_RegisterVariable(&r_water);
7466         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7467         Cvar_RegisterVariable(&r_water_clippingplanebias);
7468         Cvar_RegisterVariable(&r_water_refractdistort);
7469         Cvar_RegisterVariable(&r_water_reflectdistort);
7470         Cvar_RegisterVariable(&r_lerpsprites);
7471         Cvar_RegisterVariable(&r_lerpmodels);
7472         Cvar_RegisterVariable(&r_lerplightstyles);
7473         Cvar_RegisterVariable(&r_waterscroll);
7474         Cvar_RegisterVariable(&r_bloom);
7475         Cvar_RegisterVariable(&r_bloom_colorscale);
7476         Cvar_RegisterVariable(&r_bloom_brighten);
7477         Cvar_RegisterVariable(&r_bloom_blur);
7478         Cvar_RegisterVariable(&r_bloom_resolution);
7479         Cvar_RegisterVariable(&r_bloom_colorexponent);
7480         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7481         Cvar_RegisterVariable(&r_hdr);
7482         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7483         Cvar_RegisterVariable(&r_hdr_glowintensity);
7484         Cvar_RegisterVariable(&r_hdr_range);
7485         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7486         Cvar_RegisterVariable(&developer_texturelogging);
7487         Cvar_RegisterVariable(&gl_lightmaps);
7488         Cvar_RegisterVariable(&r_test);
7489         Cvar_RegisterVariable(&r_glsl_saturation);
7490         Cvar_RegisterVariable(&r_framedatasize);
7491         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7492                 Cvar_SetValue("r_fullbrights", 0);
7493         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7494
7495         Cvar_RegisterVariable(&r_track_sprites);
7496         Cvar_RegisterVariable(&r_track_sprites_flags);
7497         Cvar_RegisterVariable(&r_track_sprites_scalew);
7498         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7499         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7500         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7501 }
7502
7503 extern void R_Textures_Init(void);
7504 extern void GL_Draw_Init(void);
7505 extern void GL_Main_Init(void);
7506 extern void R_Shadow_Init(void);
7507 extern void R_Sky_Init(void);
7508 extern void GL_Surf_Init(void);
7509 extern void R_Particles_Init(void);
7510 extern void R_Explosion_Init(void);
7511 extern void gl_backend_init(void);
7512 extern void Sbar_Init(void);
7513 extern void R_LightningBeams_Init(void);
7514 extern void Mod_RenderInit(void);
7515 extern void Font_Init(void);
7516
7517 void Render_Init(void)
7518 {
7519         gl_backend_init();
7520         R_Textures_Init();
7521         GL_Main_Init();
7522         Font_Init();
7523         GL_Draw_Init();
7524         R_Shadow_Init();
7525         R_Sky_Init();
7526         GL_Surf_Init();
7527         Sbar_Init();
7528         R_Particles_Init();
7529         R_Explosion_Init();
7530         R_LightningBeams_Init();
7531         Mod_RenderInit();
7532 }
7533
7534 /*
7535 ===============
7536 GL_Init
7537 ===============
7538 */
7539 extern char *ENGINE_EXTENSIONS;
7540 void GL_Init (void)
7541 {
7542         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7543         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7544         gl_version = (const char *)qglGetString(GL_VERSION);
7545         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7546
7547         if (!gl_extensions)
7548                 gl_extensions = "";
7549         if (!gl_platformextensions)
7550                 gl_platformextensions = "";
7551
7552         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7553         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7554         Con_Printf("GL_VERSION: %s\n", gl_version);
7555         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7556         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7557
7558         VID_CheckExtensions();
7559
7560         // LordHavoc: report supported extensions
7561         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7562
7563         // clear to black (loading plaque will be seen over this)
7564         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7565 }
7566
7567 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7568 {
7569         int i;
7570         mplane_t *p;
7571         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7572         {
7573                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7574                 if (i == 4)
7575                         continue;
7576                 p = r_refdef.view.frustum + i;
7577                 switch(p->signbits)
7578                 {
7579                 default:
7580                 case 0:
7581                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7582                                 return true;
7583                         break;
7584                 case 1:
7585                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7586                                 return true;
7587                         break;
7588                 case 2:
7589                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7590                                 return true;
7591                         break;
7592                 case 3:
7593                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7594                                 return true;
7595                         break;
7596                 case 4:
7597                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7598                                 return true;
7599                         break;
7600                 case 5:
7601                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7602                                 return true;
7603                         break;
7604                 case 6:
7605                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7606                                 return true;
7607                         break;
7608                 case 7:
7609                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7610                                 return true;
7611                         break;
7612                 }
7613         }
7614         return false;
7615 }
7616
7617 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7618 {
7619         int i;
7620         const mplane_t *p;
7621         for (i = 0;i < numplanes;i++)
7622         {
7623                 p = planes + i;
7624                 switch(p->signbits)
7625                 {
7626                 default:
7627                 case 0:
7628                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7629                                 return true;
7630                         break;
7631                 case 1:
7632                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7633                                 return true;
7634                         break;
7635                 case 2:
7636                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7637                                 return true;
7638                         break;
7639                 case 3:
7640                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7641                                 return true;
7642                         break;
7643                 case 4:
7644                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7645                                 return true;
7646                         break;
7647                 case 5:
7648                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7649                                 return true;
7650                         break;
7651                 case 6:
7652                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7653                                 return true;
7654                         break;
7655                 case 7:
7656                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7657                                 return true;
7658                         break;
7659                 }
7660         }
7661         return false;
7662 }
7663
7664 //==================================================================================
7665
7666 // LordHavoc: this stores temporary data used within the same frame
7667
7668 qboolean r_framedata_failed;
7669 static size_t r_framedata_size;
7670 static size_t r_framedata_current;
7671 static void *r_framedata_base;
7672
7673 void R_FrameData_Reset(void)
7674 {
7675         if (r_framedata_base)
7676                 Mem_Free(r_framedata_base);
7677         r_framedata_base = NULL;
7678         r_framedata_size = 0;
7679         r_framedata_current = 0;
7680         r_framedata_failed = false;
7681 }
7682
7683 void R_FrameData_NewFrame(void)
7684 {
7685         size_t wantedsize;
7686         if (r_framedata_failed)
7687                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7688         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7689         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7690         if (r_framedata_size != wantedsize)
7691         {
7692                 r_framedata_size = wantedsize;
7693                 if (r_framedata_base)
7694                         Mem_Free(r_framedata_base);
7695                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7696         }
7697         r_framedata_current = 0;
7698         r_framedata_failed = false;
7699 }
7700
7701 void *R_FrameData_Alloc(size_t size)
7702 {
7703         void *data;
7704
7705         // align to 16 byte boundary
7706         size = (size + 15) & ~15;
7707         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7708         r_framedata_current += size;
7709
7710         // check overflow
7711         if (r_framedata_current > r_framedata_size)
7712                 r_framedata_failed = true;
7713
7714         // return NULL on everything after a failure
7715         if (r_framedata_failed)
7716                 return NULL;
7717
7718         return data;
7719 }
7720
7721 void *R_FrameData_Store(size_t size, void *data)
7722 {
7723         void *d = R_FrameData_Alloc(size);
7724         if (d)
7725                 memcpy(d, data, size);
7726         return d;
7727 }
7728
7729 //==================================================================================
7730
7731 // LordHavoc: animcache originally written by Echon, rewritten since then
7732
7733 /**
7734  * Animation cache prevents re-generating mesh data for an animated model
7735  * multiple times in one frame for lighting, shadowing, reflections, etc.
7736  */
7737
7738 void R_AnimCache_Free(void)
7739 {
7740 }
7741
7742 void R_AnimCache_ClearCache(void)
7743 {
7744         int i;
7745         entity_render_t *ent;
7746
7747         for (i = 0;i < r_refdef.scene.numentities;i++)
7748         {
7749                 ent = r_refdef.scene.entities[i];
7750                 ent->animcache_vertex3f = NULL;
7751                 ent->animcache_normal3f = NULL;
7752                 ent->animcache_svector3f = NULL;
7753                 ent->animcache_tvector3f = NULL;
7754                 ent->animcache_vertexposition = NULL;
7755                 ent->animcache_vertexmesh = NULL;
7756                 ent->animcache_vertexpositionbuffer = NULL;
7757                 ent->animcache_vertexmeshbuffer = NULL;
7758         }
7759 }
7760
7761 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7762 {
7763         int i;
7764
7765         // identical memory layout, so no need to allocate...
7766         // this also provides the vertexposition structure to everything, e.g.
7767         // depth masked rendering currently uses it even if having separate
7768         // arrays
7769         // NOTE: get rid of this optimization if changing it to e.g. 4f
7770         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7771
7772         // TODO:
7773         // get rid of following uses of VERTEXPOSITION, change to the array:
7774         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7775         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7776         // R_DrawTextureSurfaceList_DepthOnly
7777         // R_Q1BSP_DrawShadowMap
7778
7779         switch(vid.renderpath)
7780         {
7781         case RENDERPATH_GL20:
7782         case RENDERPATH_CGGL:
7783                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7784                 if (gl_mesh_separatearrays.integer)
7785                         return;
7786                 break;
7787         case RENDERPATH_D3D9:
7788         case RENDERPATH_D3D10:
7789         case RENDERPATH_D3D11:
7790                 // always need the meshbuffers
7791                 break;
7792         case RENDERPATH_GL13:
7793         case RENDERPATH_GL11:
7794                 // never need the meshbuffers
7795                 return;
7796         }
7797
7798         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7799                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7800         /*
7801         if (!ent->animcache_vertexposition)
7802                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7803         */
7804         if (ent->animcache_vertexposition)
7805         {
7806                 /*
7807                 for (i = 0;i < numvertices;i++)
7808                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7809                 */
7810                 // TODO: upload vertex buffer?
7811         }
7812         if (ent->animcache_vertexmesh)
7813         {
7814                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7815                 for (i = 0;i < numvertices;i++)
7816                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7817                 if (ent->animcache_svector3f)
7818                         for (i = 0;i < numvertices;i++)
7819                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7820                 if (ent->animcache_tvector3f)
7821                         for (i = 0;i < numvertices;i++)
7822                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7823                 if (ent->animcache_normal3f)
7824                         for (i = 0;i < numvertices;i++)
7825                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7826                 // TODO: upload vertex buffer?
7827         }
7828 }
7829
7830 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7831 {
7832         dp_model_t *model = ent->model;
7833         int numvertices;
7834         // see if it's already cached this frame
7835         if (ent->animcache_vertex3f)
7836         {
7837                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7838                 if (wantnormals || wanttangents)
7839                 {
7840                         if (ent->animcache_normal3f)
7841                                 wantnormals = false;
7842                         if (ent->animcache_svector3f)
7843                                 wanttangents = false;
7844                         if (wantnormals || wanttangents)
7845                         {
7846                                 numvertices = model->surfmesh.num_vertices;
7847                                 if (wantnormals)
7848                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7849                                 if (wanttangents)
7850                                 {
7851                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7852                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7853                                 }
7854                                 if (!r_framedata_failed)
7855                                 {
7856                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7857                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7858                                 }
7859                         }
7860                 }
7861         }
7862         else
7863         {
7864                 // see if this ent is worth caching
7865                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7866                         return false;
7867                 // get some memory for this entity and generate mesh data
7868                 numvertices = model->surfmesh.num_vertices;
7869                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7870                 if (wantnormals)
7871                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7872                 if (wanttangents)
7873                 {
7874                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7875                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7876                 }
7877                 if (!r_framedata_failed)
7878                 {
7879                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7880                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7881                 }
7882         }
7883         return !r_framedata_failed;
7884 }
7885
7886 void R_AnimCache_CacheVisibleEntities(void)
7887 {
7888         int i;
7889         qboolean wantnormals = true;
7890         qboolean wanttangents = !r_showsurfaces.integer;
7891
7892         switch(vid.renderpath)
7893         {
7894         case RENDERPATH_GL20:
7895         case RENDERPATH_CGGL:
7896         case RENDERPATH_D3D9:
7897         case RENDERPATH_D3D10:
7898         case RENDERPATH_D3D11:
7899                 break;
7900         case RENDERPATH_GL13:
7901         case RENDERPATH_GL11:
7902                 wanttangents = false;
7903                 break;
7904         }
7905
7906         if (r_shownormals.integer)
7907                 wanttangents = wantnormals = true;
7908
7909         // TODO: thread this
7910         // NOTE: R_PrepareRTLights() also caches entities
7911
7912         for (i = 0;i < r_refdef.scene.numentities;i++)
7913                 if (r_refdef.viewcache.entityvisible[i])
7914                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7915 }
7916
7917 //==================================================================================
7918
7919 static void R_View_UpdateEntityLighting (void)
7920 {
7921         int i;
7922         entity_render_t *ent;
7923         vec3_t tempdiffusenormal, avg;
7924         vec_t f, fa, fd, fdd;
7925         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7926
7927         for (i = 0;i < r_refdef.scene.numentities;i++)
7928         {
7929                 ent = r_refdef.scene.entities[i];
7930
7931                 // skip unseen models
7932                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7933                         continue;
7934
7935                 // skip bsp models
7936                 if (ent->model && ent->model->brush.num_leafs)
7937                 {
7938                         // TODO: use modellight for r_ambient settings on world?
7939                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7940                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7941                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7942                         continue;
7943                 }
7944
7945                 // fetch the lighting from the worldmodel data
7946                 VectorClear(ent->modellight_ambient);
7947                 VectorClear(ent->modellight_diffuse);
7948                 VectorClear(tempdiffusenormal);
7949                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7950                 {
7951                         vec3_t org;
7952                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7953                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7954                         if(ent->flags & RENDER_EQUALIZE)
7955                         {
7956                                 // first fix up ambient lighting...
7957                                 if(r_equalize_entities_minambient.value > 0)
7958                                 {
7959                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7960                                         if(fd > 0)
7961                                         {
7962                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7963                                                 if(fa < r_equalize_entities_minambient.value * fd)
7964                                                 {
7965                                                         // solve:
7966                                                         //   fa'/fd' = minambient
7967                                                         //   fa'+0.25*fd' = fa+0.25*fd
7968                                                         //   ...
7969                                                         //   fa' = fd' * minambient
7970                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7971                                                         //   ...
7972                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7973                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7974                                                         //   ...
7975                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7976                                                         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
7977                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7978                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7979                                                 }
7980                                         }
7981                                 }
7982
7983                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7984                                 {
7985                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7986                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7987                                         if(f > 0)
7988                                         {
7989                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7990                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7991                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7992                                         }
7993                                 }
7994                         }
7995                 }
7996                 else // highly rare
7997                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7998
7999                 // move the light direction into modelspace coordinates for lighting code
8000                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8001                 if(VectorLength2(ent->modellight_lightdir) == 0)
8002                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8003                 VectorNormalize(ent->modellight_lightdir);
8004         }
8005 }
8006
8007 #define MAX_LINEOFSIGHTTRACES 64
8008
8009 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8010 {
8011         int i;
8012         vec3_t boxmins, boxmaxs;
8013         vec3_t start;
8014         vec3_t end;
8015         dp_model_t *model = r_refdef.scene.worldmodel;
8016
8017         if (!model || !model->brush.TraceLineOfSight)
8018                 return true;
8019
8020         // expand the box a little
8021         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8022         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8023         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8024         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8025         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8026         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8027
8028         // return true if eye is inside enlarged box
8029         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8030                 return true;
8031
8032         // try center
8033         VectorCopy(eye, start);
8034         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8035         if (model->brush.TraceLineOfSight(model, start, end))
8036                 return true;
8037
8038         // try various random positions
8039         for (i = 0;i < numsamples;i++)
8040         {
8041                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8042                 if (model->brush.TraceLineOfSight(model, start, end))
8043                         return true;
8044         }
8045
8046         return false;
8047 }
8048
8049
8050 static void R_View_UpdateEntityVisible (void)
8051 {
8052         int i;
8053         int renderimask;
8054         int samples;
8055         entity_render_t *ent;
8056
8057         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8058                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8059                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8060                 :                                                          RENDER_EXTERIORMODEL;
8061         if (!r_drawviewmodel.integer)
8062                 renderimask |= RENDER_VIEWMODEL;
8063         if (!r_drawexteriormodel.integer)
8064                 renderimask |= RENDER_EXTERIORMODEL;
8065         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8066         {
8067                 // worldmodel can check visibility
8068                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8069                 for (i = 0;i < r_refdef.scene.numentities;i++)
8070                 {
8071                         ent = r_refdef.scene.entities[i];
8072                         if (!(ent->flags & renderimask))
8073                         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)))
8074                         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))
8075                                 r_refdef.viewcache.entityvisible[i] = true;
8076                 }
8077                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8078                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8079                 {
8080                         for (i = 0;i < r_refdef.scene.numentities;i++)
8081                         {
8082                                 ent = r_refdef.scene.entities[i];
8083                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8084                                 {
8085                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8086                                         if (samples < 0)
8087                                                 continue; // temp entities do pvs only
8088                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8089                                                 ent->last_trace_visibility = realtime;
8090                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8091                                                 r_refdef.viewcache.entityvisible[i] = 0;
8092                                 }
8093                         }
8094                 }
8095         }
8096         else
8097         {
8098                 // no worldmodel or it can't check visibility
8099                 for (i = 0;i < r_refdef.scene.numentities;i++)
8100                 {
8101                         ent = r_refdef.scene.entities[i];
8102                         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));
8103                 }
8104         }
8105 }
8106
8107 /// only used if skyrendermasked, and normally returns false
8108 int R_DrawBrushModelsSky (void)
8109 {
8110         int i, sky;
8111         entity_render_t *ent;
8112
8113         sky = false;
8114         for (i = 0;i < r_refdef.scene.numentities;i++)
8115         {
8116                 if (!r_refdef.viewcache.entityvisible[i])
8117                         continue;
8118                 ent = r_refdef.scene.entities[i];
8119                 if (!ent->model || !ent->model->DrawSky)
8120                         continue;
8121                 ent->model->DrawSky(ent);
8122                 sky = true;
8123         }
8124         return sky;
8125 }
8126
8127 static void R_DrawNoModel(entity_render_t *ent);
8128 static void R_DrawModels(void)
8129 {
8130         int i;
8131         entity_render_t *ent;
8132
8133         for (i = 0;i < r_refdef.scene.numentities;i++)
8134         {
8135                 if (!r_refdef.viewcache.entityvisible[i])
8136                         continue;
8137                 ent = r_refdef.scene.entities[i];
8138                 r_refdef.stats.entities++;
8139                 if (ent->model && ent->model->Draw != NULL)
8140                         ent->model->Draw(ent);
8141                 else
8142                         R_DrawNoModel(ent);
8143         }
8144 }
8145
8146 static void R_DrawModelsDepth(void)
8147 {
8148         int i;
8149         entity_render_t *ent;
8150
8151         for (i = 0;i < r_refdef.scene.numentities;i++)
8152         {
8153                 if (!r_refdef.viewcache.entityvisible[i])
8154                         continue;
8155                 ent = r_refdef.scene.entities[i];
8156                 if (ent->model && ent->model->DrawDepth != NULL)
8157                         ent->model->DrawDepth(ent);
8158         }
8159 }
8160
8161 static void R_DrawModelsDebug(void)
8162 {
8163         int i;
8164         entity_render_t *ent;
8165
8166         for (i = 0;i < r_refdef.scene.numentities;i++)
8167         {
8168                 if (!r_refdef.viewcache.entityvisible[i])
8169                         continue;
8170                 ent = r_refdef.scene.entities[i];
8171                 if (ent->model && ent->model->DrawDebug != NULL)
8172                         ent->model->DrawDebug(ent);
8173         }
8174 }
8175
8176 static void R_DrawModelsAddWaterPlanes(void)
8177 {
8178         int i;
8179         entity_render_t *ent;
8180
8181         for (i = 0;i < r_refdef.scene.numentities;i++)
8182         {
8183                 if (!r_refdef.viewcache.entityvisible[i])
8184                         continue;
8185                 ent = r_refdef.scene.entities[i];
8186                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8187                         ent->model->DrawAddWaterPlanes(ent);
8188         }
8189 }
8190
8191 static void R_View_SetFrustum(void)
8192 {
8193         int i;
8194         double slopex, slopey;
8195         vec3_t forward, left, up, origin;
8196
8197         // we can't trust r_refdef.view.forward and friends in reflected scenes
8198         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8199
8200 #if 0
8201         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8202         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8203         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8204         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8205         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8206         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8207         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8208         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8209         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8210         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8211         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8212         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8213 #endif
8214
8215 #if 0
8216         zNear = r_refdef.nearclip;
8217         nudge = 1.0 - 1.0 / (1<<23);
8218         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8219         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8220         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8221         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8222         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8223         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8224         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8225         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8226 #endif
8227
8228
8229
8230 #if 0
8231         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8232         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8233         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8234         r_refdef.view.frustum[0].dist = m[15] - m[12];
8235
8236         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8237         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8238         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8239         r_refdef.view.frustum[1].dist = m[15] + m[12];
8240
8241         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8242         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8243         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8244         r_refdef.view.frustum[2].dist = m[15] - m[13];
8245
8246         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8247         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8248         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8249         r_refdef.view.frustum[3].dist = m[15] + m[13];
8250
8251         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8252         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8253         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8254         r_refdef.view.frustum[4].dist = m[15] - m[14];
8255
8256         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8257         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8258         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8259         r_refdef.view.frustum[5].dist = m[15] + m[14];
8260 #endif
8261
8262         if (r_refdef.view.useperspective)
8263         {
8264                 slopex = 1.0 / r_refdef.view.frustum_x;
8265                 slopey = 1.0 / r_refdef.view.frustum_y;
8266                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8267                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8268                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8269                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8270                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8271
8272                 // Leaving those out was a mistake, those were in the old code, and they
8273                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8274                 // I couldn't reproduce it after adding those normalizations. --blub
8275                 VectorNormalize(r_refdef.view.frustum[0].normal);
8276                 VectorNormalize(r_refdef.view.frustum[1].normal);
8277                 VectorNormalize(r_refdef.view.frustum[2].normal);
8278                 VectorNormalize(r_refdef.view.frustum[3].normal);
8279
8280                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8281                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
8282                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
8283                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
8284                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
8285
8286                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8287                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8288                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8289                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8290                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8291         }
8292         else
8293         {
8294                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8295                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8296                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8297                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8298                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8299                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8300                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8301                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8302                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8303                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8304         }
8305         r_refdef.view.numfrustumplanes = 5;
8306
8307         if (r_refdef.view.useclipplane)
8308         {
8309                 r_refdef.view.numfrustumplanes = 6;
8310                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8311         }
8312
8313         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8314                 PlaneClassify(r_refdef.view.frustum + i);
8315
8316         // LordHavoc: note to all quake engine coders, Quake had a special case
8317         // for 90 degrees which assumed a square view (wrong), so I removed it,
8318         // Quake2 has it disabled as well.
8319
8320         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8321         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8322         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8323         //PlaneClassify(&frustum[0]);
8324
8325         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8326         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8327         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8328         //PlaneClassify(&frustum[1]);
8329
8330         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8331         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8332         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8333         //PlaneClassify(&frustum[2]);
8334
8335         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8336         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8337         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8338         //PlaneClassify(&frustum[3]);
8339
8340         // nearclip plane
8341         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8342         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8343         //PlaneClassify(&frustum[4]);
8344 }
8345
8346 void R_View_Update(void)
8347 {
8348         R_Main_ResizeViewCache();
8349         R_View_SetFrustum();
8350         R_View_WorldVisibility(r_refdef.view.useclipplane);
8351         R_View_UpdateEntityVisible();
8352         R_View_UpdateEntityLighting();
8353 }
8354
8355 void R_SetupView(qboolean allowwaterclippingplane)
8356 {
8357         const float *customclipplane = NULL;
8358         float plane[4];
8359         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8360         {
8361                 // LordHavoc: couldn't figure out how to make this approach the
8362                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8363                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8364                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8365                         dist = r_refdef.view.clipplane.dist;
8366                 plane[0] = r_refdef.view.clipplane.normal[0];
8367                 plane[1] = r_refdef.view.clipplane.normal[1];
8368                 plane[2] = r_refdef.view.clipplane.normal[2];
8369                 plane[3] = dist;
8370                 customclipplane = plane;
8371         }
8372
8373         if (!r_refdef.view.useperspective)
8374                 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);
8375         else if (vid.stencil && r_useinfinitefarclip.integer)
8376                 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);
8377         else
8378                 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);
8379         R_SetViewport(&r_refdef.view.viewport);
8380 }
8381
8382 void R_EntityMatrix(const matrix4x4_t *matrix)
8383 {
8384         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8385         {
8386                 gl_modelmatrixchanged = false;
8387                 gl_modelmatrix = *matrix;
8388                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8389                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8390                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8391                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8392                 CHECKGLERROR
8393                 switch(vid.renderpath)
8394                 {
8395                 case RENDERPATH_D3D9:
8396 #ifdef SUPPORTD3D
8397                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8398                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8399 #endif
8400                         break;
8401                 case RENDERPATH_D3D10:
8402                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8403                         break;
8404                 case RENDERPATH_D3D11:
8405                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8406                         break;
8407                 case RENDERPATH_GL20:
8408                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8409                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8410                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8411                         break;
8412                 case RENDERPATH_CGGL:
8413 #ifdef SUPPORTCG
8414                         CHECKCGERROR
8415                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8416                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8417                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8418 #endif
8419                         break;
8420                 case RENDERPATH_GL13:
8421                 case RENDERPATH_GL11:
8422                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8423                         break;
8424                 }
8425         }
8426 }
8427
8428 void R_ResetViewRendering2D(void)
8429 {
8430         r_viewport_t viewport;
8431         DrawQ_Finish();
8432
8433         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8434         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);
8435         R_SetViewport(&viewport);
8436         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8437         GL_Color(1, 1, 1, 1);
8438         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8439         GL_BlendFunc(GL_ONE, GL_ZERO);
8440         GL_AlphaTest(false);
8441         GL_ScissorTest(false);
8442         GL_DepthMask(false);
8443         GL_DepthRange(0, 1);
8444         GL_DepthTest(false);
8445         GL_DepthFunc(GL_LEQUAL);
8446         R_EntityMatrix(&identitymatrix);
8447         R_Mesh_ResetTextureState();
8448         GL_PolygonOffset(0, 0);
8449         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8450         switch(vid.renderpath)
8451         {
8452         case RENDERPATH_GL11:
8453         case RENDERPATH_GL13:
8454         case RENDERPATH_GL20:
8455         case RENDERPATH_CGGL:
8456                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8457                 break;
8458         case RENDERPATH_D3D9:
8459         case RENDERPATH_D3D10:
8460         case RENDERPATH_D3D11:
8461                 break;
8462         }
8463         GL_CullFace(GL_NONE);
8464 }
8465
8466 void R_ResetViewRendering3D(void)
8467 {
8468         DrawQ_Finish();
8469
8470         R_SetupView(true);
8471         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8472         GL_Color(1, 1, 1, 1);
8473         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8474         GL_BlendFunc(GL_ONE, GL_ZERO);
8475         GL_AlphaTest(false);
8476         GL_ScissorTest(true);
8477         GL_DepthMask(true);
8478         GL_DepthRange(0, 1);
8479         GL_DepthTest(true);
8480         GL_DepthFunc(GL_LEQUAL);
8481         R_EntityMatrix(&identitymatrix);
8482         R_Mesh_ResetTextureState();
8483         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8484         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8485         switch(vid.renderpath)
8486         {
8487         case RENDERPATH_GL11:
8488         case RENDERPATH_GL13:
8489         case RENDERPATH_GL20:
8490         case RENDERPATH_CGGL:
8491                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8492                 break;
8493         case RENDERPATH_D3D9:
8494         case RENDERPATH_D3D10:
8495         case RENDERPATH_D3D11:
8496                 break;
8497         }
8498         GL_CullFace(r_refdef.view.cullface_back);
8499 }
8500
8501 /*
8502 ================
8503 R_RenderView_UpdateViewVectors
8504 ================
8505 */
8506 static void R_RenderView_UpdateViewVectors(void)
8507 {
8508         // break apart the view matrix into vectors for various purposes
8509         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8510         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8511         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8512         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8513         // make an inverted copy of the view matrix for tracking sprites
8514         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8515 }
8516
8517 void R_RenderScene(void);
8518 void R_RenderWaterPlanes(void);
8519
8520 static void R_Water_StartFrame(void)
8521 {
8522         int i;
8523         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8524         r_waterstate_waterplane_t *p;
8525
8526         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8527                 return;
8528
8529         switch(vid.renderpath)
8530         {
8531         case RENDERPATH_GL20:
8532         case RENDERPATH_CGGL:
8533         case RENDERPATH_D3D9:
8534         case RENDERPATH_D3D10:
8535         case RENDERPATH_D3D11:
8536                 break;
8537         case RENDERPATH_GL13:
8538         case RENDERPATH_GL11:
8539                 return;
8540         }
8541
8542         // set waterwidth and waterheight to the water resolution that will be
8543         // used (often less than the screen resolution for faster rendering)
8544         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8545         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8546
8547         // calculate desired texture sizes
8548         // can't use water if the card does not support the texture size
8549         if (!r_water.integer || r_showsurfaces.integer)
8550                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8551         else if (vid.support.arb_texture_non_power_of_two)
8552         {
8553                 texturewidth = waterwidth;
8554                 textureheight = waterheight;
8555                 camerawidth = waterwidth;
8556                 cameraheight = waterheight;
8557         }
8558         else
8559         {
8560                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8561                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8562                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8563                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8564         }
8565
8566         // allocate textures as needed
8567         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8568         {
8569                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8570                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8571                 {
8572                         if (p->texture_refraction)
8573                                 R_FreeTexture(p->texture_refraction);
8574                         p->texture_refraction = NULL;
8575                         if (p->texture_reflection)
8576                                 R_FreeTexture(p->texture_reflection);
8577                         p->texture_reflection = NULL;
8578                         if (p->texture_camera)
8579                                 R_FreeTexture(p->texture_camera);
8580                         p->texture_camera = NULL;
8581                 }
8582                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8583                 r_waterstate.texturewidth = texturewidth;
8584                 r_waterstate.textureheight = textureheight;
8585                 r_waterstate.camerawidth = camerawidth;
8586                 r_waterstate.cameraheight = cameraheight;
8587         }
8588
8589         if (r_waterstate.texturewidth)
8590         {
8591                 r_waterstate.enabled = true;
8592
8593                 // when doing a reduced render (HDR) we want to use a smaller area
8594                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8595                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8596
8597                 // set up variables that will be used in shader setup
8598                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8599                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8600                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8601                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8602         }
8603
8604         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8605         r_waterstate.numwaterplanes = 0;
8606 }
8607
8608 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8609 {
8610         int triangleindex, planeindex;
8611         const int *e;
8612         vec3_t vert[3];
8613         vec3_t normal;
8614         vec3_t center;
8615         mplane_t plane;
8616         int cam_ent;
8617         r_waterstate_waterplane_t *p;
8618         texture_t *t = R_GetCurrentTexture(surface->texture);
8619         cam_ent = t->camera_entity;
8620         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8621                 cam_ent = 0;
8622
8623         // just use the first triangle with a valid normal for any decisions
8624         VectorClear(normal);
8625         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8626         {
8627                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8628                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8629                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8630                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8631                 if (VectorLength2(normal) >= 0.001)
8632                         break;
8633         }
8634
8635         VectorCopy(normal, plane.normal);
8636         VectorNormalize(plane.normal);
8637         plane.dist = DotProduct(vert[0], plane.normal);
8638         PlaneClassify(&plane);
8639         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8640         {
8641                 // skip backfaces (except if nocullface is set)
8642                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8643                         return;
8644                 VectorNegate(plane.normal, plane.normal);
8645                 plane.dist *= -1;
8646                 PlaneClassify(&plane);
8647         }
8648
8649
8650         // find a matching plane if there is one
8651         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8652                 if(p->camera_entity == t->camera_entity)
8653                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8654                                 break;
8655         if (planeindex >= r_waterstate.maxwaterplanes)
8656                 return; // nothing we can do, out of planes
8657
8658         // if this triangle does not fit any known plane rendered this frame, add one
8659         if (planeindex >= r_waterstate.numwaterplanes)
8660         {
8661                 // store the new plane
8662                 r_waterstate.numwaterplanes++;
8663                 p->plane = plane;
8664                 // clear materialflags and pvs
8665                 p->materialflags = 0;
8666                 p->pvsvalid = false;
8667                 p->camera_entity = t->camera_entity;
8668         }
8669         // merge this surface's materialflags into the waterplane
8670         p->materialflags |= t->currentmaterialflags;
8671         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8672         {
8673                 // merge this surface's PVS into the waterplane
8674                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8675                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8676                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8677                 {
8678                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8679                         p->pvsvalid = true;
8680                 }
8681         }
8682 }
8683
8684 static void R_Water_ProcessPlanes(void)
8685 {
8686         r_refdef_view_t originalview;
8687         r_refdef_view_t myview;
8688         int planeindex;
8689         r_waterstate_waterplane_t *p;
8690         vec3_t visorigin;
8691
8692         originalview = r_refdef.view;
8693
8694         // make sure enough textures are allocated
8695         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8696         {
8697                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8698                 {
8699                         if (!p->texture_refraction)
8700                                 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);
8701                         if (!p->texture_refraction)
8702                                 goto error;
8703                 }
8704                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8705                 {
8706                         if (!p->texture_camera)
8707                                 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);
8708                         if (!p->texture_camera)
8709                                 goto error;
8710                 }
8711
8712                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8713                 {
8714                         if (!p->texture_reflection)
8715                                 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);
8716                         if (!p->texture_reflection)
8717                                 goto error;
8718                 }
8719         }
8720
8721         // render views
8722         r_refdef.view = originalview;
8723         r_refdef.view.showdebug = false;
8724         r_refdef.view.width = r_waterstate.waterwidth;
8725         r_refdef.view.height = r_waterstate.waterheight;
8726         r_refdef.view.useclipplane = true;
8727         myview = r_refdef.view;
8728         r_waterstate.renderingscene = true;
8729         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8730         {
8731                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8732                 {
8733                         r_refdef.view = myview;
8734                         // render reflected scene and copy into texture
8735                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8736                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8737                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8738                         r_refdef.view.clipplane = p->plane;
8739                         // reverse the cullface settings for this render
8740                         r_refdef.view.cullface_front = GL_FRONT;
8741                         r_refdef.view.cullface_back = GL_BACK;
8742                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8743                         {
8744                                 r_refdef.view.usecustompvs = true;
8745                                 if (p->pvsvalid)
8746                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8747                                 else
8748                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8749                         }
8750
8751                         R_ResetViewRendering3D();
8752                         R_ClearScreen(r_refdef.fogenabled);
8753                         R_View_Update();
8754                         R_RenderScene();
8755
8756                         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);
8757                 }
8758
8759                 // render the normal view scene and copy into texture
8760                 // (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)
8761                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8762                 {
8763                         r_waterstate.renderingrefraction = true;
8764                         r_refdef.view = myview;
8765
8766                         r_refdef.view.clipplane = p->plane;
8767                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8768                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8769
8770                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8771                         {
8772                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8773                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8774                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8775                                 R_RenderView_UpdateViewVectors();
8776                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8777                                 {
8778                                         r_refdef.view.usecustompvs = true;
8779                                         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);
8780                                 }
8781                         }
8782
8783                         PlaneClassify(&r_refdef.view.clipplane);
8784
8785                         R_ResetViewRendering3D();
8786                         R_ClearScreen(r_refdef.fogenabled);
8787                         R_View_Update();
8788                         R_RenderScene();
8789
8790                         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);
8791                         r_waterstate.renderingrefraction = false;
8792                 }
8793                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8794                 {
8795                         r_refdef.view = myview;
8796
8797                         r_refdef.view.clipplane = p->plane;
8798                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8799                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8800
8801                         r_refdef.view.width = r_waterstate.camerawidth;
8802                         r_refdef.view.height = r_waterstate.cameraheight;
8803                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8804                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8805
8806                         if(p->camera_entity)
8807                         {
8808                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8809                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8810                         }
8811
8812                         // reverse the cullface settings for this render
8813                         r_refdef.view.cullface_front = GL_FRONT;
8814                         r_refdef.view.cullface_back = GL_BACK;
8815                         // also reverse the view matrix
8816                         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
8817                         R_RenderView_UpdateViewVectors();
8818                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8819                         {
8820                                 r_refdef.view.usecustompvs = true;
8821                                 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);
8822                         }
8823                         
8824                         // camera needs no clipplane
8825                         r_refdef.view.useclipplane = false;
8826
8827                         PlaneClassify(&r_refdef.view.clipplane);
8828
8829                         R_ResetViewRendering3D();
8830                         R_ClearScreen(r_refdef.fogenabled);
8831                         R_View_Update();
8832                         R_RenderScene();
8833
8834                         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);
8835                         r_waterstate.renderingrefraction = false;
8836                 }
8837
8838         }
8839         r_waterstate.renderingscene = false;
8840         r_refdef.view = originalview;
8841         R_ResetViewRendering3D();
8842         R_ClearScreen(r_refdef.fogenabled);
8843         R_View_Update();
8844         return;
8845 error:
8846         r_refdef.view = originalview;
8847         r_waterstate.renderingscene = false;
8848         Cvar_SetValueQuick(&r_water, 0);
8849         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8850         return;
8851 }
8852
8853 void R_Bloom_StartFrame(void)
8854 {
8855         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8856
8857         switch(vid.renderpath)
8858         {
8859         case RENDERPATH_GL20:
8860         case RENDERPATH_CGGL:
8861         case RENDERPATH_D3D9:
8862         case RENDERPATH_D3D10:
8863         case RENDERPATH_D3D11:
8864                 break;
8865         case RENDERPATH_GL13:
8866         case RENDERPATH_GL11:
8867                 return;
8868         }
8869
8870         // set bloomwidth and bloomheight to the bloom resolution that will be
8871         // used (often less than the screen resolution for faster rendering)
8872         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8873         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8874         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8875         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8876         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8877
8878         // calculate desired texture sizes
8879         if (vid.support.arb_texture_non_power_of_two)
8880         {
8881                 screentexturewidth = r_refdef.view.width;
8882                 screentextureheight = r_refdef.view.height;
8883                 bloomtexturewidth = r_bloomstate.bloomwidth;
8884                 bloomtextureheight = r_bloomstate.bloomheight;
8885         }
8886         else
8887         {
8888                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8889                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8890                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8891                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8892         }
8893
8894         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))
8895         {
8896                 Cvar_SetValueQuick(&r_hdr, 0);
8897                 Cvar_SetValueQuick(&r_bloom, 0);
8898                 Cvar_SetValueQuick(&r_motionblur, 0);
8899                 Cvar_SetValueQuick(&r_damageblur, 0);
8900         }
8901
8902         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)))
8903                 screentexturewidth = screentextureheight = 0;
8904         if (!r_hdr.integer && !r_bloom.integer)
8905                 bloomtexturewidth = bloomtextureheight = 0;
8906
8907         // allocate textures as needed
8908         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8909         {
8910                 if (r_bloomstate.texture_screen)
8911                         R_FreeTexture(r_bloomstate.texture_screen);
8912                 r_bloomstate.texture_screen = NULL;
8913                 r_bloomstate.screentexturewidth = screentexturewidth;
8914                 r_bloomstate.screentextureheight = screentextureheight;
8915                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8916                         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);
8917         }
8918         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8919         {
8920                 if (r_bloomstate.texture_bloom)
8921                         R_FreeTexture(r_bloomstate.texture_bloom);
8922                 r_bloomstate.texture_bloom = NULL;
8923                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8924                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8925                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8926                         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);
8927         }
8928
8929         // when doing a reduced render (HDR) we want to use a smaller area
8930         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8931         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8932         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8933         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8934         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8935
8936         // set up a texcoord array for the full resolution screen image
8937         // (we have to keep this around to copy back during final render)
8938         r_bloomstate.screentexcoord2f[0] = 0;
8939         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8940         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8941         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8942         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8943         r_bloomstate.screentexcoord2f[5] = 0;
8944         r_bloomstate.screentexcoord2f[6] = 0;
8945         r_bloomstate.screentexcoord2f[7] = 0;
8946
8947         // set up a texcoord array for the reduced resolution bloom image
8948         // (which will be additive blended over the screen image)
8949         r_bloomstate.bloomtexcoord2f[0] = 0;
8950         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8951         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8952         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8953         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8954         r_bloomstate.bloomtexcoord2f[5] = 0;
8955         r_bloomstate.bloomtexcoord2f[6] = 0;
8956         r_bloomstate.bloomtexcoord2f[7] = 0;
8957
8958         switch(vid.renderpath)
8959         {
8960         case RENDERPATH_GL11:
8961         case RENDERPATH_GL13:
8962         case RENDERPATH_GL20:
8963         case RENDERPATH_CGGL:
8964                 break;
8965         case RENDERPATH_D3D9:
8966         case RENDERPATH_D3D10:
8967         case RENDERPATH_D3D11:
8968                 {
8969                         int i;
8970                         for (i = 0;i < 4;i++)
8971                         {
8972                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8973                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8974                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8975                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8976                         }
8977                 }
8978                 break;
8979         }
8980
8981         if (r_hdr.integer || r_bloom.integer)
8982         {
8983                 r_bloomstate.enabled = true;
8984                 r_bloomstate.hdr = r_hdr.integer != 0;
8985         }
8986
8987         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);
8988 }
8989
8990 void R_Bloom_CopyBloomTexture(float colorscale)
8991 {
8992         r_refdef.stats.bloom++;
8993
8994         // scale down screen texture to the bloom texture size
8995         CHECKGLERROR
8996         R_SetViewport(&r_bloomstate.viewport);
8997         GL_BlendFunc(GL_ONE, GL_ZERO);
8998         GL_Color(colorscale, colorscale, colorscale, 1);
8999         // 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...
9000         switch(vid.renderpath)
9001         {
9002         case RENDERPATH_GL11:
9003         case RENDERPATH_GL13:
9004         case RENDERPATH_GL20:
9005         case RENDERPATH_CGGL:
9006                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9007                 break;
9008         case RENDERPATH_D3D9:
9009         case RENDERPATH_D3D10:
9010         case RENDERPATH_D3D11:
9011                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9012                 break;
9013         }
9014         // TODO: do boxfilter scale-down in shader?
9015         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9016         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9017         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9018
9019         // we now have a bloom image in the framebuffer
9020         // copy it into the bloom image texture for later processing
9021         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);
9022         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9023 }
9024
9025 void R_Bloom_CopyHDRTexture(void)
9026 {
9027         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);
9028         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9029 }
9030
9031 void R_Bloom_MakeTexture(void)
9032 {
9033         int x, range, dir;
9034         float xoffset, yoffset, r, brighten;
9035
9036         r_refdef.stats.bloom++;
9037
9038         R_ResetViewRendering2D();
9039
9040         // we have a bloom image in the framebuffer
9041         CHECKGLERROR
9042         R_SetViewport(&r_bloomstate.viewport);
9043
9044         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9045         {
9046                 x *= 2;
9047                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9048                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9049                 GL_Color(r,r,r,1);
9050                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9051                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9052                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9053                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9054
9055                 // copy the vertically blurred bloom view to a texture
9056                 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);
9057                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9058         }
9059
9060         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9061         brighten = r_bloom_brighten.value;
9062         if (r_hdr.integer)
9063                 brighten *= r_hdr_range.value;
9064         brighten = sqrt(brighten);
9065         if(range >= 1)
9066                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9067         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9068
9069         for (dir = 0;dir < 2;dir++)
9070         {
9071                 // blend on at multiple vertical offsets to achieve a vertical blur
9072                 // TODO: do offset blends using GLSL
9073                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9074                 GL_BlendFunc(GL_ONE, GL_ZERO);
9075                 for (x = -range;x <= range;x++)
9076                 {
9077                         if (!dir){xoffset = 0;yoffset = x;}
9078                         else {xoffset = x;yoffset = 0;}
9079                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9080                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9081                         // compute a texcoord array with the specified x and y offset
9082                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9083                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9084                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9085                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9086                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9087                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9088                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9089                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9090                         // this r value looks like a 'dot' particle, fading sharply to
9091                         // black at the edges
9092                         // (probably not realistic but looks good enough)
9093                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9094                         //r = brighten/(range*2+1);
9095                         r = brighten / (range * 2 + 1);
9096                         if(range >= 1)
9097                                 r *= (1 - x*x/(float)(range*range));
9098                         GL_Color(r, r, r, 1);
9099                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9100                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9101                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9102                         GL_BlendFunc(GL_ONE, GL_ONE);
9103                 }
9104
9105                 // copy the vertically blurred bloom view to a texture
9106                 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);
9107                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9108         }
9109 }
9110
9111 void R_HDR_RenderBloomTexture(void)
9112 {
9113         int oldwidth, oldheight;
9114         float oldcolorscale;
9115
9116         oldcolorscale = r_refdef.view.colorscale;
9117         oldwidth = r_refdef.view.width;
9118         oldheight = r_refdef.view.height;
9119         r_refdef.view.width = r_bloomstate.bloomwidth;
9120         r_refdef.view.height = r_bloomstate.bloomheight;
9121
9122         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9123         // TODO: add exposure compensation features
9124         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9125
9126         r_refdef.view.showdebug = false;
9127         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9128
9129         R_ResetViewRendering3D();
9130
9131         R_ClearScreen(r_refdef.fogenabled);
9132         if (r_timereport_active)
9133                 R_TimeReport("HDRclear");
9134
9135         R_View_Update();
9136         if (r_timereport_active)
9137                 R_TimeReport("visibility");
9138
9139         // only do secondary renders with HDR if r_hdr is 2 or higher
9140         r_waterstate.numwaterplanes = 0;
9141         if (r_waterstate.enabled && r_hdr.integer >= 2)
9142                 R_RenderWaterPlanes();
9143
9144         r_refdef.view.showdebug = true;
9145         R_RenderScene();
9146         r_waterstate.numwaterplanes = 0;
9147
9148         R_ResetViewRendering2D();
9149
9150         R_Bloom_CopyHDRTexture();
9151         R_Bloom_MakeTexture();
9152
9153         // restore the view settings
9154         r_refdef.view.width = oldwidth;
9155         r_refdef.view.height = oldheight;
9156         r_refdef.view.colorscale = oldcolorscale;
9157
9158         R_ResetViewRendering3D();
9159
9160         R_ClearScreen(r_refdef.fogenabled);
9161         if (r_timereport_active)
9162                 R_TimeReport("viewclear");
9163 }
9164
9165 static void R_BlendView(void)
9166 {
9167         unsigned int permutation;
9168         float uservecs[4][4];
9169
9170         switch (vid.renderpath)
9171         {
9172         case RENDERPATH_GL20:
9173         case RENDERPATH_CGGL:
9174         case RENDERPATH_D3D9:
9175         case RENDERPATH_D3D10:
9176         case RENDERPATH_D3D11:
9177                 permutation =
9178                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9179                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9180                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9181                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9182                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9183
9184                 if (r_bloomstate.texture_screen)
9185                 {
9186                         // make sure the buffer is available
9187                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9188
9189                         R_ResetViewRendering2D();
9190
9191                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9192                         {
9193                                 // declare variables
9194                                 float speed;
9195                                 static float avgspeed;
9196
9197                                 speed = VectorLength(cl.movement_velocity);
9198
9199                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9200                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9201
9202                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9203                                 speed = bound(0, speed, 1);
9204                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9205
9206                                 // calculate values into a standard alpha
9207                                 cl.motionbluralpha = 1 - exp(-
9208                                                 (
9209                                                  (r_motionblur.value * speed / 80)
9210                                                  +
9211                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9212                                                 )
9213                                                 /
9214                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9215                                            );
9216
9217                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9218                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9219                                 // apply the blur
9220                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9221                                 {
9222                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9223                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9224                                         switch(vid.renderpath)
9225                                         {
9226                                         case RENDERPATH_GL11:
9227                                         case RENDERPATH_GL13:
9228                                         case RENDERPATH_GL20:
9229                                         case RENDERPATH_CGGL:
9230                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9231                                                 break;
9232                                         case RENDERPATH_D3D9:
9233                                         case RENDERPATH_D3D10:
9234                                         case RENDERPATH_D3D11:
9235                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9236                                                 break;
9237                                         }
9238                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9239                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9240                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9241                                 }
9242                         }
9243
9244                         // copy view into the screen texture
9245                         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);
9246                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9247                 }
9248                 else if (!r_bloomstate.texture_bloom)
9249                 {
9250                         // we may still have to do view tint...
9251                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9252                         {
9253                                 // apply a color tint to the whole view
9254                                 R_ResetViewRendering2D();
9255                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9256                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9257                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9258                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9259                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9260                         }
9261                         break; // no screen processing, no bloom, skip it
9262                 }
9263
9264                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9265                 {
9266                         // render simple bloom effect
9267                         // copy the screen and shrink it and darken it for the bloom process
9268                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9269                         // make the bloom texture
9270                         R_Bloom_MakeTexture();
9271                 }
9272
9273 #if _MSC_VER >= 1400
9274 #define sscanf sscanf_s
9275 #endif
9276                 memset(uservecs, 0, sizeof(uservecs));
9277                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9278                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9279                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9280                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9281
9282                 R_ResetViewRendering2D();
9283                 GL_Color(1, 1, 1, 1);
9284                 GL_BlendFunc(GL_ONE, GL_ZERO);
9285
9286                 switch(vid.renderpath)
9287                 {
9288                 case RENDERPATH_GL20:
9289                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9290                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9291                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9292                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9293                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9294                         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]);
9295                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9296                         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]);
9297                         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]);
9298                         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]);
9299                         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]);
9300                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9301                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9302                         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);
9303                         break;
9304                 case RENDERPATH_CGGL:
9305 #ifdef SUPPORTCG
9306                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9307                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9308                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9309                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9310                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9311                         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
9312                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9313                         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
9314                         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
9315                         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
9316                         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
9317                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9318                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9319                         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);
9320 #endif
9321                         break;
9322                 case RENDERPATH_D3D9:
9323 #ifdef SUPPORTD3D
9324                         // 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...
9325                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9326                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9327                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9328                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9329                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9330                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9331                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9332                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9333                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9334                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9335                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9336                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9337                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9338                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9339 #endif
9340                         break;
9341                 case RENDERPATH_D3D10:
9342                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9343                         break;
9344                 case RENDERPATH_D3D11:
9345                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9346                         break;
9347                 default:
9348                         break;
9349                 }
9350                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9351                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9352                 break;
9353         case RENDERPATH_GL13:
9354         case RENDERPATH_GL11:
9355                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9356                 {
9357                         // apply a color tint to the whole view
9358                         R_ResetViewRendering2D();
9359                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9360                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9361                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9362                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9363                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9364                 }
9365                 break;
9366         }
9367 }
9368
9369 matrix4x4_t r_waterscrollmatrix;
9370
9371 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9372 {
9373         if (r_refdef.fog_density)
9374         {
9375                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9376                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9377                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9378
9379                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9380                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9381                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9382                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9383
9384                 {
9385                         vec3_t fogvec;
9386                         VectorCopy(r_refdef.fogcolor, fogvec);
9387                         //   color.rgb *= ContrastBoost * SceneBrightness;
9388                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9389                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9390                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9391                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9392                 }
9393         }
9394 }
9395
9396 void R_UpdateVariables(void)
9397 {
9398         R_Textures_Frame();
9399
9400         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9401
9402         r_refdef.farclip = r_farclip_base.value;
9403         if (r_refdef.scene.worldmodel)
9404                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9405         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9406
9407         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9408                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9409         r_refdef.polygonfactor = 0;
9410         r_refdef.polygonoffset = 0;
9411         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9412         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9413
9414         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9415         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9416         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9417         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9418         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9419         if (r_showsurfaces.integer)
9420         {
9421                 r_refdef.scene.rtworld = false;
9422                 r_refdef.scene.rtworldshadows = false;
9423                 r_refdef.scene.rtdlight = false;
9424                 r_refdef.scene.rtdlightshadows = false;
9425                 r_refdef.lightmapintensity = 0;
9426         }
9427
9428         if (gamemode == GAME_NEHAHRA)
9429         {
9430                 if (gl_fogenable.integer)
9431                 {
9432                         r_refdef.oldgl_fogenable = true;
9433                         r_refdef.fog_density = gl_fogdensity.value;
9434                         r_refdef.fog_red = gl_fogred.value;
9435                         r_refdef.fog_green = gl_foggreen.value;
9436                         r_refdef.fog_blue = gl_fogblue.value;
9437                         r_refdef.fog_alpha = 1;
9438                         r_refdef.fog_start = 0;
9439                         r_refdef.fog_end = gl_skyclip.value;
9440                         r_refdef.fog_height = 1<<30;
9441                         r_refdef.fog_fadedepth = 128;
9442                 }
9443                 else if (r_refdef.oldgl_fogenable)
9444                 {
9445                         r_refdef.oldgl_fogenable = false;
9446                         r_refdef.fog_density = 0;
9447                         r_refdef.fog_red = 0;
9448                         r_refdef.fog_green = 0;
9449                         r_refdef.fog_blue = 0;
9450                         r_refdef.fog_alpha = 0;
9451                         r_refdef.fog_start = 0;
9452                         r_refdef.fog_end = 0;
9453                         r_refdef.fog_height = 1<<30;
9454                         r_refdef.fog_fadedepth = 128;
9455                 }
9456         }
9457
9458         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9459         r_refdef.fog_start = max(0, r_refdef.fog_start);
9460         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9461
9462         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9463
9464         if (r_refdef.fog_density && r_drawfog.integer)
9465         {
9466                 r_refdef.fogenabled = true;
9467                 // this is the point where the fog reaches 0.9986 alpha, which we
9468                 // consider a good enough cutoff point for the texture
9469                 // (0.9986 * 256 == 255.6)
9470                 if (r_fog_exp2.integer)
9471                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9472                 else
9473                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9474                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9475                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9476                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9477                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9478                         R_BuildFogHeightTexture();
9479                 // fog color was already set
9480                 // update the fog texture
9481                 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)
9482                         R_BuildFogTexture();
9483                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9484                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9485         }
9486         else
9487                 r_refdef.fogenabled = false;
9488
9489         switch(vid.renderpath)
9490         {
9491         case RENDERPATH_GL20:
9492         case RENDERPATH_CGGL:
9493         case RENDERPATH_D3D9:
9494         case RENDERPATH_D3D10:
9495         case RENDERPATH_D3D11:
9496                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9497                 {
9498                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9499                         {
9500                                 // build GLSL gamma texture
9501 #define RAMPWIDTH 256
9502                                 unsigned short ramp[RAMPWIDTH * 3];
9503                                 unsigned char rampbgr[RAMPWIDTH][4];
9504                                 int i;
9505
9506                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9507
9508                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9509                                 for(i = 0; i < RAMPWIDTH; ++i)
9510                                 {
9511                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9512                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9513                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9514                                         rampbgr[i][3] = 0;
9515                                 }
9516                                 if (r_texture_gammaramps)
9517                                 {
9518                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9519                                 }
9520                                 else
9521                                 {
9522                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9523                                 }
9524                         }
9525                 }
9526                 else
9527                 {
9528                         // remove GLSL gamma texture
9529                 }
9530                 break;
9531         case RENDERPATH_GL13:
9532         case RENDERPATH_GL11:
9533                 break;
9534         }
9535 }
9536
9537 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9538 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9539 /*
9540 ================
9541 R_SelectScene
9542 ================
9543 */
9544 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9545         if( scenetype != r_currentscenetype ) {
9546                 // store the old scenetype
9547                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9548                 r_currentscenetype = scenetype;
9549                 // move in the new scene
9550                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9551         }
9552 }
9553
9554 /*
9555 ================
9556 R_GetScenePointer
9557 ================
9558 */
9559 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9560 {
9561         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9562         if( scenetype == r_currentscenetype ) {
9563                 return &r_refdef.scene;
9564         } else {
9565                 return &r_scenes_store[ scenetype ];
9566         }
9567 }
9568
9569 /*
9570 ================
9571 R_RenderView
9572 ================
9573 */
9574 void R_RenderView(void)
9575 {
9576         if (r_timereport_active)
9577                 R_TimeReport("start");
9578         r_textureframe++; // used only by R_GetCurrentTexture
9579         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9580
9581         if (!r_drawentities.integer)
9582                 r_refdef.scene.numentities = 0;
9583
9584         R_AnimCache_ClearCache();
9585         R_FrameData_NewFrame();
9586
9587         if (r_refdef.view.isoverlay)
9588         {
9589                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9590                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9591                 R_TimeReport("depthclear");
9592
9593                 r_refdef.view.showdebug = false;
9594
9595                 r_waterstate.enabled = false;
9596                 r_waterstate.numwaterplanes = 0;
9597
9598                 R_RenderScene();
9599
9600                 CHECKGLERROR
9601                 return;
9602         }
9603
9604         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9605                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9606
9607         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9608
9609         R_RenderView_UpdateViewVectors();
9610
9611         R_Shadow_UpdateWorldLightSelection();
9612
9613         R_Bloom_StartFrame();
9614         R_Water_StartFrame();
9615
9616         CHECKGLERROR
9617         if (r_timereport_active)
9618                 R_TimeReport("viewsetup");
9619
9620         R_ResetViewRendering3D();
9621
9622         if (r_refdef.view.clear || r_refdef.fogenabled)
9623         {
9624                 R_ClearScreen(r_refdef.fogenabled);
9625                 if (r_timereport_active)
9626                         R_TimeReport("viewclear");
9627         }
9628         r_refdef.view.clear = true;
9629
9630         // this produces a bloom texture to be used in R_BlendView() later
9631         if (r_hdr.integer && r_bloomstate.bloomwidth)
9632         {
9633                 R_HDR_RenderBloomTexture();
9634                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9635                 r_textureframe++; // used only by R_GetCurrentTexture
9636         }
9637
9638         r_refdef.view.showdebug = true;
9639
9640         R_View_Update();
9641         if (r_timereport_active)
9642                 R_TimeReport("visibility");
9643
9644         r_waterstate.numwaterplanes = 0;
9645         if (r_waterstate.enabled)
9646                 R_RenderWaterPlanes();
9647
9648         R_RenderScene();
9649         r_waterstate.numwaterplanes = 0;
9650
9651         R_BlendView();
9652         if (r_timereport_active)
9653                 R_TimeReport("blendview");
9654
9655         GL_Scissor(0, 0, vid.width, vid.height);
9656         GL_ScissorTest(false);
9657         CHECKGLERROR
9658 }
9659
9660 void R_RenderWaterPlanes(void)
9661 {
9662         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9663         {
9664                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9665                 if (r_timereport_active)
9666                         R_TimeReport("waterworld");
9667         }
9668
9669         // don't let sound skip if going slow
9670         if (r_refdef.scene.extraupdate)
9671                 S_ExtraUpdate ();
9672
9673         R_DrawModelsAddWaterPlanes();
9674         if (r_timereport_active)
9675                 R_TimeReport("watermodels");
9676
9677         if (r_waterstate.numwaterplanes)
9678         {
9679                 R_Water_ProcessPlanes();
9680                 if (r_timereport_active)
9681                         R_TimeReport("waterscenes");
9682         }
9683 }
9684
9685 extern void R_DrawLightningBeams (void);
9686 extern void VM_CL_AddPolygonsToMeshQueue (void);
9687 extern void R_DrawPortals (void);
9688 extern cvar_t cl_locs_show;
9689 static void R_DrawLocs(void);
9690 static void R_DrawEntityBBoxes(void);
9691 static void R_DrawModelDecals(void);
9692 extern void R_DrawModelShadows(void);
9693 extern void R_DrawModelShadowMaps(void);
9694 extern cvar_t cl_decals_newsystem;
9695 extern qboolean r_shadow_usingdeferredprepass;
9696 void R_RenderScene(void)
9697 {
9698         qboolean shadowmapping = false;
9699
9700         if (r_timereport_active)
9701                 R_TimeReport("beginscene");
9702
9703         r_refdef.stats.renders++;
9704
9705         R_UpdateFogColor();
9706
9707         // don't let sound skip if going slow
9708         if (r_refdef.scene.extraupdate)
9709                 S_ExtraUpdate ();
9710
9711         R_MeshQueue_BeginScene();
9712
9713         R_SkyStartFrame();
9714
9715         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);
9716
9717         if (r_timereport_active)
9718                 R_TimeReport("skystartframe");
9719
9720         if (cl.csqc_vidvars.drawworld)
9721         {
9722                 // don't let sound skip if going slow
9723                 if (r_refdef.scene.extraupdate)
9724                         S_ExtraUpdate ();
9725
9726                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9727                 {
9728                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9729                         if (r_timereport_active)
9730                                 R_TimeReport("worldsky");
9731                 }
9732
9733                 if (R_DrawBrushModelsSky() && r_timereport_active)
9734                         R_TimeReport("bmodelsky");
9735
9736                 if (skyrendermasked && skyrenderlater)
9737                 {
9738                         // we have to force off the water clipping plane while rendering sky
9739                         R_SetupView(false);
9740                         R_Sky();
9741                         R_SetupView(true);
9742                         if (r_timereport_active)
9743                                 R_TimeReport("sky");
9744                 }
9745         }
9746
9747         R_AnimCache_CacheVisibleEntities();
9748         if (r_timereport_active)
9749                 R_TimeReport("animation");
9750
9751         R_Shadow_PrepareLights();
9752         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9753                 R_Shadow_PrepareModelShadows();
9754         if (r_timereport_active)
9755                 R_TimeReport("preparelights");
9756
9757         if (R_Shadow_ShadowMappingEnabled())
9758                 shadowmapping = true;
9759
9760         if (r_shadow_usingdeferredprepass)
9761                 R_Shadow_DrawPrepass();
9762
9763         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9764         {
9765                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9766                 if (r_timereport_active)
9767                         R_TimeReport("worlddepth");
9768         }
9769         if (r_depthfirst.integer >= 2)
9770         {
9771                 R_DrawModelsDepth();
9772                 if (r_timereport_active)
9773                         R_TimeReport("modeldepth");
9774         }
9775
9776         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9777         {
9778                 R_DrawModelShadowMaps();
9779                 R_ResetViewRendering3D();
9780                 // don't let sound skip if going slow
9781                 if (r_refdef.scene.extraupdate)
9782                         S_ExtraUpdate ();
9783         }
9784
9785         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9786         {
9787                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9788                 if (r_timereport_active)
9789                         R_TimeReport("world");
9790         }
9791
9792         // don't let sound skip if going slow
9793         if (r_refdef.scene.extraupdate)
9794                 S_ExtraUpdate ();
9795
9796         R_DrawModels();
9797         if (r_timereport_active)
9798                 R_TimeReport("models");
9799
9800         // don't let sound skip if going slow
9801         if (r_refdef.scene.extraupdate)
9802                 S_ExtraUpdate ();
9803
9804         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9805         {
9806                 R_DrawModelShadows();
9807                 R_ResetViewRendering3D();
9808                 // don't let sound skip if going slow
9809                 if (r_refdef.scene.extraupdate)
9810                         S_ExtraUpdate ();
9811         }
9812
9813         if (!r_shadow_usingdeferredprepass)
9814         {
9815                 R_Shadow_DrawLights();
9816                 if (r_timereport_active)
9817                         R_TimeReport("rtlights");
9818         }
9819
9820         // don't let sound skip if going slow
9821         if (r_refdef.scene.extraupdate)
9822                 S_ExtraUpdate ();
9823
9824         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9825         {
9826                 R_DrawModelShadows();
9827                 R_ResetViewRendering3D();
9828                 // don't let sound skip if going slow
9829                 if (r_refdef.scene.extraupdate)
9830                         S_ExtraUpdate ();
9831         }
9832
9833         if (cl.csqc_vidvars.drawworld)
9834         {
9835                 if (cl_decals_newsystem.integer)
9836                 {
9837                         R_DrawModelDecals();
9838                         if (r_timereport_active)
9839                                 R_TimeReport("modeldecals");
9840                 }
9841                 else
9842                 {
9843                         R_DrawDecals();
9844                         if (r_timereport_active)
9845                                 R_TimeReport("decals");
9846                 }
9847
9848                 R_DrawParticles();
9849                 if (r_timereport_active)
9850                         R_TimeReport("particles");
9851
9852                 R_DrawExplosions();
9853                 if (r_timereport_active)
9854                         R_TimeReport("explosions");
9855
9856                 R_DrawLightningBeams();
9857                 if (r_timereport_active)
9858                         R_TimeReport("lightning");
9859         }
9860
9861         VM_CL_AddPolygonsToMeshQueue();
9862
9863         if (r_refdef.view.showdebug)
9864         {
9865                 if (cl_locs_show.integer)
9866                 {
9867                         R_DrawLocs();
9868                         if (r_timereport_active)
9869                                 R_TimeReport("showlocs");
9870                 }
9871
9872                 if (r_drawportals.integer)
9873                 {
9874                         R_DrawPortals();
9875                         if (r_timereport_active)
9876                                 R_TimeReport("portals");
9877                 }
9878
9879                 if (r_showbboxes.value > 0)
9880                 {
9881                         R_DrawEntityBBoxes();
9882                         if (r_timereport_active)
9883                                 R_TimeReport("bboxes");
9884                 }
9885         }
9886
9887         R_MeshQueue_RenderTransparent();
9888         if (r_timereport_active)
9889                 R_TimeReport("drawtrans");
9890
9891         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))
9892         {
9893                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9894                 if (r_timereport_active)
9895                         R_TimeReport("worlddebug");
9896                 R_DrawModelsDebug();
9897                 if (r_timereport_active)
9898                         R_TimeReport("modeldebug");
9899         }
9900
9901         if (cl.csqc_vidvars.drawworld)
9902         {
9903                 R_Shadow_DrawCoronas();
9904                 if (r_timereport_active)
9905                         R_TimeReport("coronas");
9906         }
9907
9908         // don't let sound skip if going slow
9909         if (r_refdef.scene.extraupdate)
9910                 S_ExtraUpdate ();
9911
9912         R_ResetViewRendering2D();
9913 }
9914
9915 static const unsigned short bboxelements[36] =
9916 {
9917         5, 1, 3, 5, 3, 7,
9918         6, 2, 0, 6, 0, 4,
9919         7, 3, 2, 7, 2, 6,
9920         4, 0, 1, 4, 1, 5,
9921         4, 5, 7, 4, 7, 6,
9922         1, 0, 2, 1, 2, 3,
9923 };
9924
9925 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9926 {
9927         int i;
9928         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9929
9930         RSurf_ActiveWorldEntity();
9931
9932         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9933         GL_DepthMask(false);
9934         GL_DepthRange(0, 1);
9935         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9936         R_Mesh_ResetTextureState();
9937
9938         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9939         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9940         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9941         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9942         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9943         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9944         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9945         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9946         R_FillColors(color4f, 8, cr, cg, cb, ca);
9947         if (r_refdef.fogenabled)
9948         {
9949                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9950                 {
9951                         f1 = RSurf_FogVertex(v);
9952                         f2 = 1 - f1;
9953                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9954                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9955                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9956                 }
9957         }
9958         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9959         R_Mesh_ResetTextureState();
9960         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9961         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9962 }
9963
9964 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9965 {
9966         int i;
9967         float color[4];
9968         prvm_edict_t *edict;
9969         prvm_prog_t *prog_save = prog;
9970
9971         // this function draws bounding boxes of server entities
9972         if (!sv.active)
9973                 return;
9974
9975         GL_CullFace(GL_NONE);
9976         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9977
9978         prog = 0;
9979         SV_VM_Begin();
9980         for (i = 0;i < numsurfaces;i++)
9981         {
9982                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9983                 switch ((int)edict->fields.server->solid)
9984                 {
9985                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9986                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9987                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9988                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9989                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9990                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9991                 }
9992                 color[3] *= r_showbboxes.value;
9993                 color[3] = bound(0, color[3], 1);
9994                 GL_DepthTest(!r_showdisabledepthtest.integer);
9995                 GL_CullFace(r_refdef.view.cullface_front);
9996                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9997         }
9998         SV_VM_End();
9999         prog = prog_save;
10000 }
10001
10002 static void R_DrawEntityBBoxes(void)
10003 {
10004         int i;
10005         prvm_edict_t *edict;
10006         vec3_t center;
10007         prvm_prog_t *prog_save = prog;
10008
10009         // this function draws bounding boxes of server entities
10010         if (!sv.active)
10011                 return;
10012
10013         prog = 0;
10014         SV_VM_Begin();
10015         for (i = 0;i < prog->num_edicts;i++)
10016         {
10017                 edict = PRVM_EDICT_NUM(i);
10018                 if (edict->priv.server->free)
10019                         continue;
10020                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10021                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10022                         continue;
10023                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10024                         continue;
10025                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10026                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10027         }
10028         SV_VM_End();
10029         prog = prog_save;
10030 }
10031
10032 static const int nomodelelement3i[24] =
10033 {
10034         5, 2, 0,
10035         5, 1, 2,
10036         5, 0, 3,
10037         5, 3, 1,
10038         0, 2, 4,
10039         2, 1, 4,
10040         3, 0, 4,
10041         1, 3, 4
10042 };
10043
10044 static const unsigned short nomodelelement3s[24] =
10045 {
10046         5, 2, 0,
10047         5, 1, 2,
10048         5, 0, 3,
10049         5, 3, 1,
10050         0, 2, 4,
10051         2, 1, 4,
10052         3, 0, 4,
10053         1, 3, 4
10054 };
10055
10056 static const float nomodelvertex3f[6*3] =
10057 {
10058         -16,   0,   0,
10059          16,   0,   0,
10060           0, -16,   0,
10061           0,  16,   0,
10062           0,   0, -16,
10063           0,   0,  16
10064 };
10065
10066 static const float nomodelcolor4f[6*4] =
10067 {
10068         0.0f, 0.0f, 0.5f, 1.0f,
10069         0.0f, 0.0f, 0.5f, 1.0f,
10070         0.0f, 0.5f, 0.0f, 1.0f,
10071         0.0f, 0.5f, 0.0f, 1.0f,
10072         0.5f, 0.0f, 0.0f, 1.0f,
10073         0.5f, 0.0f, 0.0f, 1.0f
10074 };
10075
10076 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10077 {
10078         int i;
10079         float f1, f2, *c;
10080         float color4f[6*4];
10081
10082         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);
10083
10084         // this is only called once per entity so numsurfaces is always 1, and
10085         // surfacelist is always {0}, so this code does not handle batches
10086
10087         if (rsurface.ent_flags & RENDER_ADDITIVE)
10088         {
10089                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10090                 GL_DepthMask(false);
10091         }
10092         else if (rsurface.colormod[3] < 1)
10093         {
10094                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10095                 GL_DepthMask(false);
10096         }
10097         else
10098         {
10099                 GL_BlendFunc(GL_ONE, GL_ZERO);
10100                 GL_DepthMask(true);
10101         }
10102         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10103         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10104         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10105         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10106         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10107         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10108         for (i = 0, c = color4f;i < 6;i++, c += 4)
10109         {
10110                 c[0] *= rsurface.colormod[0];
10111                 c[1] *= rsurface.colormod[1];
10112                 c[2] *= rsurface.colormod[2];
10113                 c[3] *= rsurface.colormod[3];
10114         }
10115         if (r_refdef.fogenabled)
10116         {
10117                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10118                 {
10119                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10120                         f2 = 1 - f1;
10121                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10122                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10123                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10124                 }
10125         }
10126         R_Mesh_ResetTextureState();
10127         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10128         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10129 }
10130
10131 void R_DrawNoModel(entity_render_t *ent)
10132 {
10133         vec3_t org;
10134         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10135         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10136                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10137         else
10138                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10139 }
10140
10141 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10142 {
10143         vec3_t right1, right2, diff, normal;
10144
10145         VectorSubtract (org2, org1, normal);
10146
10147         // calculate 'right' vector for start
10148         VectorSubtract (r_refdef.view.origin, org1, diff);
10149         CrossProduct (normal, diff, right1);
10150         VectorNormalize (right1);
10151
10152         // calculate 'right' vector for end
10153         VectorSubtract (r_refdef.view.origin, org2, diff);
10154         CrossProduct (normal, diff, right2);
10155         VectorNormalize (right2);
10156
10157         vert[ 0] = org1[0] + width * right1[0];
10158         vert[ 1] = org1[1] + width * right1[1];
10159         vert[ 2] = org1[2] + width * right1[2];
10160         vert[ 3] = org1[0] - width * right1[0];
10161         vert[ 4] = org1[1] - width * right1[1];
10162         vert[ 5] = org1[2] - width * right1[2];
10163         vert[ 6] = org2[0] - width * right2[0];
10164         vert[ 7] = org2[1] - width * right2[1];
10165         vert[ 8] = org2[2] - width * right2[2];
10166         vert[ 9] = org2[0] + width * right2[0];
10167         vert[10] = org2[1] + width * right2[1];
10168         vert[11] = org2[2] + width * right2[2];
10169 }
10170
10171 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)
10172 {
10173         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10174         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10175         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10176         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10177         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10178         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10179         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10180         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10181         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10182         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10183         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10184         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10185 }
10186
10187 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10188 {
10189         int i;
10190         float *vertex3f;
10191         float v[3];
10192         VectorSet(v, x, y, z);
10193         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10194                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10195                         break;
10196         if (i == mesh->numvertices)
10197         {
10198                 if (mesh->numvertices < mesh->maxvertices)
10199                 {
10200                         VectorCopy(v, vertex3f);
10201                         mesh->numvertices++;
10202                 }
10203                 return mesh->numvertices;
10204         }
10205         else
10206                 return i;
10207 }
10208
10209 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10210 {
10211         int i;
10212         int *e, element[3];
10213         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10214         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10215         e = mesh->element3i + mesh->numtriangles * 3;
10216         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10217         {
10218                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10219                 if (mesh->numtriangles < mesh->maxtriangles)
10220                 {
10221                         *e++ = element[0];
10222                         *e++ = element[1];
10223                         *e++ = element[2];
10224                         mesh->numtriangles++;
10225                 }
10226                 element[1] = element[2];
10227         }
10228 }
10229
10230 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10231 {
10232         int i;
10233         int *e, element[3];
10234         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10235         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10236         e = mesh->element3i + mesh->numtriangles * 3;
10237         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10238         {
10239                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10240                 if (mesh->numtriangles < mesh->maxtriangles)
10241                 {
10242                         *e++ = element[0];
10243                         *e++ = element[1];
10244                         *e++ = element[2];
10245                         mesh->numtriangles++;
10246                 }
10247                 element[1] = element[2];
10248         }
10249 }
10250
10251 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10252 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10253 {
10254         int planenum, planenum2;
10255         int w;
10256         int tempnumpoints;
10257         mplane_t *plane, *plane2;
10258         double maxdist;
10259         double temppoints[2][256*3];
10260         // figure out how large a bounding box we need to properly compute this brush
10261         maxdist = 0;
10262         for (w = 0;w < numplanes;w++)
10263                 maxdist = max(maxdist, fabs(planes[w].dist));
10264         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10265         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10266         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10267         {
10268                 w = 0;
10269                 tempnumpoints = 4;
10270                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10271                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10272                 {
10273                         if (planenum2 == planenum)
10274                                 continue;
10275                         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);
10276                         w = !w;
10277                 }
10278                 if (tempnumpoints < 3)
10279                         continue;
10280                 // generate elements forming a triangle fan for this polygon
10281                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10282         }
10283 }
10284
10285 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)
10286 {
10287         texturelayer_t *layer;
10288         layer = t->currentlayers + t->currentnumlayers++;
10289         layer->type = type;
10290         layer->depthmask = depthmask;
10291         layer->blendfunc1 = blendfunc1;
10292         layer->blendfunc2 = blendfunc2;
10293         layer->texture = texture;
10294         layer->texmatrix = *matrix;
10295         layer->color[0] = r;
10296         layer->color[1] = g;
10297         layer->color[2] = b;
10298         layer->color[3] = a;
10299 }
10300
10301 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10302 {
10303         if(parms[0] == 0 && parms[1] == 0)
10304                 return false;
10305         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10306                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10307                         return false;
10308         return true;
10309 }
10310
10311 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10312 {
10313         double index, f;
10314         index = parms[2] + r_refdef.scene.time * parms[3];
10315         index -= floor(index);
10316         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10317         {
10318         default:
10319         case Q3WAVEFUNC_NONE:
10320         case Q3WAVEFUNC_NOISE:
10321         case Q3WAVEFUNC_COUNT:
10322                 f = 0;
10323                 break;
10324         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10325         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10326         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10327         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10328         case Q3WAVEFUNC_TRIANGLE:
10329                 index *= 4;
10330                 f = index - floor(index);
10331                 if (index < 1)
10332                         f = f;
10333                 else if (index < 2)
10334                         f = 1 - f;
10335                 else if (index < 3)
10336                         f = -f;
10337                 else
10338                         f = -(1 - f);
10339                 break;
10340         }
10341         f = parms[0] + parms[1] * f;
10342         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10343                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10344         return (float) f;
10345 }
10346
10347 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10348 {
10349         int w, h, idx;
10350         float f;
10351         float tcmat[12];
10352         matrix4x4_t matrix, temp;
10353         switch(tcmod->tcmod)
10354         {
10355                 case Q3TCMOD_COUNT:
10356                 case Q3TCMOD_NONE:
10357                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10358                                 matrix = r_waterscrollmatrix;
10359                         else
10360                                 matrix = identitymatrix;
10361                         break;
10362                 case Q3TCMOD_ENTITYTRANSLATE:
10363                         // this is used in Q3 to allow the gamecode to control texcoord
10364                         // scrolling on the entity, which is not supported in darkplaces yet.
10365                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10366                         break;
10367                 case Q3TCMOD_ROTATE:
10368                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10369                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10370                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10371                         break;
10372                 case Q3TCMOD_SCALE:
10373                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10374                         break;
10375                 case Q3TCMOD_SCROLL:
10376                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10377                         break;
10378                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10379                         w = (int) tcmod->parms[0];
10380                         h = (int) tcmod->parms[1];
10381                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10382                         f = f - floor(f);
10383                         idx = (int) floor(f * w * h);
10384                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10385                         break;
10386                 case Q3TCMOD_STRETCH:
10387                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10388                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10389                         break;
10390                 case Q3TCMOD_TRANSFORM:
10391                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10392                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10393                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10394                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10395                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10396                         break;
10397                 case Q3TCMOD_TURBULENT:
10398                         // this is handled in the RSurf_PrepareVertices function
10399                         matrix = identitymatrix;
10400                         break;
10401         }
10402         temp = *texmatrix;
10403         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10404 }
10405
10406 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10407 {
10408         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10409         char name[MAX_QPATH];
10410         skinframe_t *skinframe;
10411         unsigned char pixels[296*194];
10412         strlcpy(cache->name, skinname, sizeof(cache->name));
10413         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10414         if (developer_loading.integer)
10415                 Con_Printf("loading %s\n", name);
10416         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10417         if (!skinframe || !skinframe->base)
10418         {
10419                 unsigned char *f;
10420                 fs_offset_t filesize;
10421                 skinframe = NULL;
10422                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10423                 if (f)
10424                 {
10425                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10426                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10427                         Mem_Free(f);
10428                 }
10429         }
10430         cache->skinframe = skinframe;
10431 }
10432
10433 texture_t *R_GetCurrentTexture(texture_t *t)
10434 {
10435         int i;
10436         const entity_render_t *ent = rsurface.entity;
10437         dp_model_t *model = ent->model;
10438         q3shaderinfo_layer_tcmod_t *tcmod;
10439
10440         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10441                 return t->currentframe;
10442         t->update_lastrenderframe = r_textureframe;
10443         t->update_lastrenderentity = (void *)ent;
10444
10445         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10446                 t->camera_entity = ent->entitynumber;
10447         else
10448                 t->camera_entity = 0;
10449
10450         // switch to an alternate material if this is a q1bsp animated material
10451         {
10452                 texture_t *texture = t;
10453                 int s = rsurface.ent_skinnum;
10454                 if ((unsigned int)s >= (unsigned int)model->numskins)
10455                         s = 0;
10456                 if (model->skinscenes)
10457                 {
10458                         if (model->skinscenes[s].framecount > 1)
10459                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10460                         else
10461                                 s = model->skinscenes[s].firstframe;
10462                 }
10463                 if (s > 0)
10464                         t = t + s * model->num_surfaces;
10465                 if (t->animated)
10466                 {
10467                         // use an alternate animation if the entity's frame is not 0,
10468                         // and only if the texture has an alternate animation
10469                         if (rsurface.ent_alttextures && t->anim_total[1])
10470                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10471                         else
10472                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10473                 }
10474                 texture->currentframe = t;
10475         }
10476
10477         // update currentskinframe to be a qw skin or animation frame
10478         if (rsurface.ent_qwskin >= 0)
10479         {
10480                 i = rsurface.ent_qwskin;
10481                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10482                 {
10483                         r_qwskincache_size = cl.maxclients;
10484                         if (r_qwskincache)
10485                                 Mem_Free(r_qwskincache);
10486                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10487                 }
10488                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10489                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10490                 t->currentskinframe = r_qwskincache[i].skinframe;
10491                 if (t->currentskinframe == NULL)
10492                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10493         }
10494         else if (t->numskinframes >= 2)
10495                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10496         if (t->backgroundnumskinframes >= 2)
10497                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10498
10499         t->currentmaterialflags = t->basematerialflags;
10500         t->currentalpha = rsurface.colormod[3];
10501         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10502                 t->currentalpha *= r_wateralpha.value;
10503         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10504                 t->currentalpha *= t->r_water_wateralpha;
10505         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10506                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10507         if (!(rsurface.ent_flags & RENDER_LIGHT))
10508                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10509         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10510         {
10511                 // pick a model lighting mode
10512                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10513                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10514                 else
10515                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10516         }
10517         if (rsurface.ent_flags & RENDER_ADDITIVE)
10518                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10519         else if (t->currentalpha < 1)
10520                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10521         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10522                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10523         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10524                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10525         if (t->backgroundnumskinframes)
10526                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10527         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10528         {
10529                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10530                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10531         }
10532         else
10533                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10534         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10535                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10536
10537         // there is no tcmod
10538         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10539         {
10540                 t->currenttexmatrix = r_waterscrollmatrix;
10541                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10542         }
10543         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10544         {
10545                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10546                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10547         }
10548
10549         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10550                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10551         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10552                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10553
10554         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10555         if (t->currentskinframe->qpixels)
10556                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10557         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10558         if (!t->basetexture)
10559                 t->basetexture = r_texture_notexture;
10560         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10561         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10562         t->nmaptexture = t->currentskinframe->nmap;
10563         if (!t->nmaptexture)
10564                 t->nmaptexture = r_texture_blanknormalmap;
10565         t->glosstexture = r_texture_black;
10566         t->glowtexture = t->currentskinframe->glow;
10567         t->fogtexture = t->currentskinframe->fog;
10568         t->reflectmasktexture = t->currentskinframe->reflect;
10569         if (t->backgroundnumskinframes)
10570         {
10571                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10572                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10573                 t->backgroundglosstexture = r_texture_black;
10574                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10575                 if (!t->backgroundnmaptexture)
10576                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10577         }
10578         else
10579         {
10580                 t->backgroundbasetexture = r_texture_white;
10581                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10582                 t->backgroundglosstexture = r_texture_black;
10583                 t->backgroundglowtexture = NULL;
10584         }
10585         t->specularpower = r_shadow_glossexponent.value;
10586         // TODO: store reference values for these in the texture?
10587         t->specularscale = 0;
10588         if (r_shadow_gloss.integer > 0)
10589         {
10590                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10591                 {
10592                         if (r_shadow_glossintensity.value > 0)
10593                         {
10594                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10595                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10596                                 t->specularscale = r_shadow_glossintensity.value;
10597                         }
10598                 }
10599                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10600                 {
10601                         t->glosstexture = r_texture_white;
10602                         t->backgroundglosstexture = r_texture_white;
10603                         t->specularscale = r_shadow_gloss2intensity.value;
10604                         t->specularpower = r_shadow_gloss2exponent.value;
10605                 }
10606         }
10607         t->specularscale *= t->specularscalemod;
10608         t->specularpower *= t->specularpowermod;
10609
10610         // lightmaps mode looks bad with dlights using actual texturing, so turn
10611         // off the colormap and glossmap, but leave the normalmap on as it still
10612         // accurately represents the shading involved
10613         if (gl_lightmaps.integer)
10614         {
10615                 t->basetexture = r_texture_grey128;
10616                 t->pantstexture = r_texture_black;
10617                 t->shirttexture = r_texture_black;
10618                 t->nmaptexture = r_texture_blanknormalmap;
10619                 t->glosstexture = r_texture_black;
10620                 t->glowtexture = NULL;
10621                 t->fogtexture = NULL;
10622                 t->reflectmasktexture = NULL;
10623                 t->backgroundbasetexture = NULL;
10624                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10625                 t->backgroundglosstexture = r_texture_black;
10626                 t->backgroundglowtexture = NULL;
10627                 t->specularscale = 0;
10628                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10629         }
10630
10631         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10632         VectorClear(t->dlightcolor);
10633         t->currentnumlayers = 0;
10634         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10635         {
10636                 int blendfunc1, blendfunc2;
10637                 qboolean depthmask;
10638                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10639                 {
10640                         blendfunc1 = GL_SRC_ALPHA;
10641                         blendfunc2 = GL_ONE;
10642                 }
10643                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10644                 {
10645                         blendfunc1 = GL_SRC_ALPHA;
10646                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10647                 }
10648                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10649                 {
10650                         blendfunc1 = t->customblendfunc[0];
10651                         blendfunc2 = t->customblendfunc[1];
10652                 }
10653                 else
10654                 {
10655                         blendfunc1 = GL_ONE;
10656                         blendfunc2 = GL_ZERO;
10657                 }
10658                 // don't colormod evilblend textures
10659                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10660                         VectorSet(t->lightmapcolor, 1, 1, 1);
10661                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10662                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10663                 {
10664                         // fullbright is not affected by r_refdef.lightmapintensity
10665                         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]);
10666                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10667                                 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]);
10668                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10669                                 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]);
10670                 }
10671                 else
10672                 {
10673                         vec3_t ambientcolor;
10674                         float colorscale;
10675                         // set the color tint used for lights affecting this surface
10676                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10677                         colorscale = 2;
10678                         // q3bsp has no lightmap updates, so the lightstylevalue that
10679                         // would normally be baked into the lightmap must be
10680                         // applied to the color
10681                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10682                         if (model->type == mod_brushq3)
10683                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10684                         colorscale *= r_refdef.lightmapintensity;
10685                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10686                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10687                         // basic lit geometry
10688                         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]);
10689                         // add pants/shirt if needed
10690                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10691                                 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]);
10692                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10693                                 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]);
10694                         // now add ambient passes if needed
10695                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10696                         {
10697                                 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]);
10698                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10699                                         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]);
10700                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10701                                         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]);
10702                         }
10703                 }
10704                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10705                         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]);
10706                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10707                 {
10708                         // if this is opaque use alpha blend which will darken the earlier
10709                         // passes cheaply.
10710                         //
10711                         // if this is an alpha blended material, all the earlier passes
10712                         // were darkened by fog already, so we only need to add the fog
10713                         // color ontop through the fog mask texture
10714                         //
10715                         // if this is an additive blended material, all the earlier passes
10716                         // were darkened by fog already, and we should not add fog color
10717                         // (because the background was not darkened, there is no fog color
10718                         // that was lost behind it).
10719                         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]);
10720                 }
10721         }
10722
10723         return t->currentframe;
10724 }
10725
10726 rsurfacestate_t rsurface;
10727
10728 void R_Mesh_ResizeArrays(int newvertices)
10729 {
10730         unsigned char *base;
10731         size_t size;
10732         if (rsurface.array_size >= newvertices)
10733                 return;
10734         if (rsurface.array_base)
10735                 Mem_Free(rsurface.array_base);
10736         rsurface.array_size = (newvertices + 1023) & ~1023;
10737         size = 0;
10738         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10739         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10740         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10741         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10742         size += rsurface.array_size * sizeof(float[3]);
10743         size += rsurface.array_size * sizeof(float[3]);
10744         size += rsurface.array_size * sizeof(float[3]);
10745         size += rsurface.array_size * sizeof(float[3]);
10746         size += rsurface.array_size * sizeof(float[3]);
10747         size += rsurface.array_size * sizeof(float[3]);
10748         size += rsurface.array_size * sizeof(float[3]);
10749         size += rsurface.array_size * sizeof(float[3]);
10750         size += rsurface.array_size * sizeof(float[4]);
10751         size += rsurface.array_size * sizeof(float[2]);
10752         size += rsurface.array_size * sizeof(float[2]);
10753         size += rsurface.array_size * sizeof(float[4]);
10754         size += rsurface.array_size * sizeof(int[3]);
10755         size += rsurface.array_size * sizeof(unsigned short[3]);
10756         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10757         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10758         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10759         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10760         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10761         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10762         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10763         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10764         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10765         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10766         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10767         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10768         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10769         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10770         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10771         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10772         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10773         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10774         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10775 }
10776
10777 void RSurf_ActiveWorldEntity(void)
10778 {
10779         dp_model_t *model = r_refdef.scene.worldmodel;
10780         //if (rsurface.entity == r_refdef.scene.worldentity)
10781         //      return;
10782         rsurface.entity = r_refdef.scene.worldentity;
10783         rsurface.skeleton = NULL;
10784         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10785         rsurface.ent_skinnum = 0;
10786         rsurface.ent_qwskin = -1;
10787         rsurface.ent_shadertime = 0;
10788         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10789         if (rsurface.array_size < model->surfmesh.num_vertices)
10790                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10791         rsurface.matrix = identitymatrix;
10792         rsurface.inversematrix = identitymatrix;
10793         rsurface.matrixscale = 1;
10794         rsurface.inversematrixscale = 1;
10795         R_EntityMatrix(&identitymatrix);
10796         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10797         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10798         rsurface.fograngerecip = r_refdef.fograngerecip;
10799         rsurface.fogheightfade = r_refdef.fogheightfade;
10800         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10801         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10802         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10803         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10804         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10805         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10806         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10807         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10808         rsurface.colormod[3] = 1;
10809         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);
10810         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10811         rsurface.frameblend[0].lerp = 1;
10812         rsurface.ent_alttextures = false;
10813         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10814         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10815         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10816         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10817         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10818         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10819         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10820         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10821         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10822         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10823         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10824         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10825         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10826         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10827         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10828         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10829         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10830         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10831         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10832         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10833         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10834         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10835         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10836         rsurface.modelelement3i = model->surfmesh.data_element3i;
10837         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10838         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10839         rsurface.modelelement3s = model->surfmesh.data_element3s;
10840         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10841         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10842         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10843         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10844         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10845         rsurface.modelsurfaces = model->data_surfaces;
10846         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10847         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10848         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10849         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10850         rsurface.modelgeneratedvertex = false;
10851         rsurface.batchgeneratedvertex = false;
10852         rsurface.batchfirstvertex = 0;
10853         rsurface.batchnumvertices = 0;
10854         rsurface.batchfirsttriangle = 0;
10855         rsurface.batchnumtriangles = 0;
10856         rsurface.batchvertex3f  = NULL;
10857         rsurface.batchvertex3f_vertexbuffer = NULL;
10858         rsurface.batchvertex3f_bufferoffset = 0;
10859         rsurface.batchsvector3f = NULL;
10860         rsurface.batchsvector3f_vertexbuffer = NULL;
10861         rsurface.batchsvector3f_bufferoffset = 0;
10862         rsurface.batchtvector3f = NULL;
10863         rsurface.batchtvector3f_vertexbuffer = NULL;
10864         rsurface.batchtvector3f_bufferoffset = 0;
10865         rsurface.batchnormal3f  = NULL;
10866         rsurface.batchnormal3f_vertexbuffer = NULL;
10867         rsurface.batchnormal3f_bufferoffset = 0;
10868         rsurface.batchlightmapcolor4f = NULL;
10869         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10870         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10871         rsurface.batchtexcoordtexture2f = NULL;
10872         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10873         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10874         rsurface.batchtexcoordlightmap2f = NULL;
10875         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10876         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10877         rsurface.batchvertexmesh = NULL;
10878         rsurface.batchvertexmeshbuffer = NULL;
10879         rsurface.batchvertexposition = NULL;
10880         rsurface.batchvertexpositionbuffer = NULL;
10881         rsurface.batchelement3i = NULL;
10882         rsurface.batchelement3i_indexbuffer = NULL;
10883         rsurface.batchelement3i_bufferoffset = 0;
10884         rsurface.batchelement3s = NULL;
10885         rsurface.batchelement3s_indexbuffer = NULL;
10886         rsurface.batchelement3s_bufferoffset = 0;
10887         rsurface.passcolor4f = NULL;
10888         rsurface.passcolor4f_vertexbuffer = NULL;
10889         rsurface.passcolor4f_bufferoffset = 0;
10890 }
10891
10892 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10893 {
10894         dp_model_t *model = ent->model;
10895         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10896         //      return;
10897         rsurface.entity = (entity_render_t *)ent;
10898         rsurface.skeleton = ent->skeleton;
10899         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10900         rsurface.ent_skinnum = ent->skinnum;
10901         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;
10902         rsurface.ent_shadertime = ent->shadertime;
10903         rsurface.ent_flags = ent->flags;
10904         if (rsurface.array_size < model->surfmesh.num_vertices)
10905                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10906         rsurface.matrix = ent->matrix;
10907         rsurface.inversematrix = ent->inversematrix;
10908         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10909         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10910         R_EntityMatrix(&rsurface.matrix);
10911         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10912         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10913         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10914         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10915         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10916         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10917         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10918         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10919         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10920         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10921         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10922         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10923         rsurface.colormod[3] = ent->alpha;
10924         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10925         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10926         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10927         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10928         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10929         if (ent->model->brush.submodel && !prepass)
10930         {
10931                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10932                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10933         }
10934         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10935         {
10936                 if (ent->animcache_vertex3f && !r_framedata_failed)
10937                 {
10938                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10939                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10940                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10941                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10942                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10943                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10944                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10945                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10946                 }
10947                 else if (wanttangents)
10948                 {
10949                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10950                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10951                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10952                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10953                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10954                         rsurface.modelvertexmesh = NULL;
10955                         rsurface.modelvertexmeshbuffer = NULL;
10956                         rsurface.modelvertexposition = NULL;
10957                         rsurface.modelvertexpositionbuffer = NULL;
10958                 }
10959                 else if (wantnormals)
10960                 {
10961                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10962                         rsurface.modelsvector3f = NULL;
10963                         rsurface.modeltvector3f = NULL;
10964                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10965                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10966                         rsurface.modelvertexmesh = NULL;
10967                         rsurface.modelvertexmeshbuffer = NULL;
10968                         rsurface.modelvertexposition = NULL;
10969                         rsurface.modelvertexpositionbuffer = NULL;
10970                 }
10971                 else
10972                 {
10973                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10974                         rsurface.modelsvector3f = NULL;
10975                         rsurface.modeltvector3f = NULL;
10976                         rsurface.modelnormal3f = NULL;
10977                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10978                         rsurface.modelvertexmesh = NULL;
10979                         rsurface.modelvertexmeshbuffer = NULL;
10980                         rsurface.modelvertexposition = NULL;
10981                         rsurface.modelvertexpositionbuffer = NULL;
10982                 }
10983                 rsurface.modelvertex3f_vertexbuffer = 0;
10984                 rsurface.modelvertex3f_bufferoffset = 0;
10985                 rsurface.modelsvector3f_vertexbuffer = 0;
10986                 rsurface.modelsvector3f_bufferoffset = 0;
10987                 rsurface.modeltvector3f_vertexbuffer = 0;
10988                 rsurface.modeltvector3f_bufferoffset = 0;
10989                 rsurface.modelnormal3f_vertexbuffer = 0;
10990                 rsurface.modelnormal3f_bufferoffset = 0;
10991                 rsurface.modelgeneratedvertex = true;
10992         }
10993         else
10994         {
10995                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10996                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10997                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10998                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10999                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11000                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11001                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11002                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11003                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11004                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11005                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11006                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11007                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11008                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11009                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11010                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11011                 rsurface.modelgeneratedvertex = false;
11012         }
11013         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11014         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11015         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11016         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11017         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11018         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11019         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11020         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11021         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11022         rsurface.modelelement3i = model->surfmesh.data_element3i;
11023         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11024         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11025         rsurface.modelelement3s = model->surfmesh.data_element3s;
11026         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11027         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11028         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11029         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11030         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11031         rsurface.modelsurfaces = model->data_surfaces;
11032         rsurface.batchgeneratedvertex = false;
11033         rsurface.batchfirstvertex = 0;
11034         rsurface.batchnumvertices = 0;
11035         rsurface.batchfirsttriangle = 0;
11036         rsurface.batchnumtriangles = 0;
11037         rsurface.batchvertex3f  = NULL;
11038         rsurface.batchvertex3f_vertexbuffer = NULL;
11039         rsurface.batchvertex3f_bufferoffset = 0;
11040         rsurface.batchsvector3f = NULL;
11041         rsurface.batchsvector3f_vertexbuffer = NULL;
11042         rsurface.batchsvector3f_bufferoffset = 0;
11043         rsurface.batchtvector3f = NULL;
11044         rsurface.batchtvector3f_vertexbuffer = NULL;
11045         rsurface.batchtvector3f_bufferoffset = 0;
11046         rsurface.batchnormal3f  = NULL;
11047         rsurface.batchnormal3f_vertexbuffer = NULL;
11048         rsurface.batchnormal3f_bufferoffset = 0;
11049         rsurface.batchlightmapcolor4f = NULL;
11050         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11051         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11052         rsurface.batchtexcoordtexture2f = NULL;
11053         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11054         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11055         rsurface.batchtexcoordlightmap2f = NULL;
11056         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11057         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11058         rsurface.batchvertexmesh = NULL;
11059         rsurface.batchvertexmeshbuffer = NULL;
11060         rsurface.batchvertexposition = NULL;
11061         rsurface.batchvertexpositionbuffer = NULL;
11062         rsurface.batchelement3i = NULL;
11063         rsurface.batchelement3i_indexbuffer = NULL;
11064         rsurface.batchelement3i_bufferoffset = 0;
11065         rsurface.batchelement3s = NULL;
11066         rsurface.batchelement3s_indexbuffer = NULL;
11067         rsurface.batchelement3s_bufferoffset = 0;
11068         rsurface.passcolor4f = NULL;
11069         rsurface.passcolor4f_vertexbuffer = NULL;
11070         rsurface.passcolor4f_bufferoffset = 0;
11071 }
11072
11073 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)
11074 {
11075         int i;
11076
11077         rsurface.entity = r_refdef.scene.worldentity;
11078         rsurface.skeleton = NULL;
11079         rsurface.ent_skinnum = 0;
11080         rsurface.ent_qwskin = -1;
11081         rsurface.ent_shadertime = shadertime;
11082         rsurface.ent_flags = entflags;
11083         rsurface.modelnumvertices = numvertices;
11084         rsurface.modelnumtriangles = numtriangles;
11085         if (rsurface.array_size < rsurface.modelnumvertices)
11086                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11087         rsurface.matrix = *matrix;
11088         rsurface.inversematrix = *inversematrix;
11089         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11090         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11091         R_EntityMatrix(&rsurface.matrix);
11092         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11093         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11094         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11095         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11096         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11097         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11098         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11099         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11100         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11101         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11102         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11103         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11104         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);
11105         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11106         rsurface.frameblend[0].lerp = 1;
11107         rsurface.ent_alttextures = false;
11108         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11109         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11110         if (wanttangents)
11111         {
11112                 rsurface.modelvertex3f = vertex3f;
11113                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11114                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11115                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11116         }
11117         else if (wantnormals)
11118         {
11119                 rsurface.modelvertex3f = vertex3f;
11120                 rsurface.modelsvector3f = NULL;
11121                 rsurface.modeltvector3f = NULL;
11122                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11123         }
11124         else
11125         {
11126                 rsurface.modelvertex3f = vertex3f;
11127                 rsurface.modelsvector3f = NULL;
11128                 rsurface.modeltvector3f = NULL;
11129                 rsurface.modelnormal3f = NULL;
11130         }
11131         rsurface.modelvertexmesh = NULL;
11132         rsurface.modelvertexmeshbuffer = NULL;
11133         rsurface.modelvertexposition = NULL;
11134         rsurface.modelvertexpositionbuffer = NULL;
11135         rsurface.modelvertex3f_vertexbuffer = 0;
11136         rsurface.modelvertex3f_bufferoffset = 0;
11137         rsurface.modelsvector3f_vertexbuffer = 0;
11138         rsurface.modelsvector3f_bufferoffset = 0;
11139         rsurface.modeltvector3f_vertexbuffer = 0;
11140         rsurface.modeltvector3f_bufferoffset = 0;
11141         rsurface.modelnormal3f_vertexbuffer = 0;
11142         rsurface.modelnormal3f_bufferoffset = 0;
11143         rsurface.modelgeneratedvertex = true;
11144         rsurface.modellightmapcolor4f  = color4f;
11145         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11146         rsurface.modellightmapcolor4f_bufferoffset = 0;
11147         rsurface.modeltexcoordtexture2f  = texcoord2f;
11148         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11149         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11150         rsurface.modeltexcoordlightmap2f  = NULL;
11151         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11152         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11153         rsurface.modelelement3i = element3i;
11154         rsurface.modelelement3i_indexbuffer = NULL;
11155         rsurface.modelelement3i_bufferoffset = 0;
11156         rsurface.modelelement3s = element3s;
11157         rsurface.modelelement3s_indexbuffer = NULL;
11158         rsurface.modelelement3s_bufferoffset = 0;
11159         rsurface.modellightmapoffsets = NULL;
11160         rsurface.modelsurfaces = NULL;
11161         rsurface.batchgeneratedvertex = false;
11162         rsurface.batchfirstvertex = 0;
11163         rsurface.batchnumvertices = 0;
11164         rsurface.batchfirsttriangle = 0;
11165         rsurface.batchnumtriangles = 0;
11166         rsurface.batchvertex3f  = NULL;
11167         rsurface.batchvertex3f_vertexbuffer = NULL;
11168         rsurface.batchvertex3f_bufferoffset = 0;
11169         rsurface.batchsvector3f = NULL;
11170         rsurface.batchsvector3f_vertexbuffer = NULL;
11171         rsurface.batchsvector3f_bufferoffset = 0;
11172         rsurface.batchtvector3f = NULL;
11173         rsurface.batchtvector3f_vertexbuffer = NULL;
11174         rsurface.batchtvector3f_bufferoffset = 0;
11175         rsurface.batchnormal3f  = NULL;
11176         rsurface.batchnormal3f_vertexbuffer = NULL;
11177         rsurface.batchnormal3f_bufferoffset = 0;
11178         rsurface.batchlightmapcolor4f = NULL;
11179         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11180         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11181         rsurface.batchtexcoordtexture2f = NULL;
11182         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11183         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11184         rsurface.batchtexcoordlightmap2f = NULL;
11185         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11186         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11187         rsurface.batchvertexmesh = NULL;
11188         rsurface.batchvertexmeshbuffer = NULL;
11189         rsurface.batchvertexposition = NULL;
11190         rsurface.batchvertexpositionbuffer = NULL;
11191         rsurface.batchelement3i = NULL;
11192         rsurface.batchelement3i_indexbuffer = NULL;
11193         rsurface.batchelement3i_bufferoffset = 0;
11194         rsurface.batchelement3s = NULL;
11195         rsurface.batchelement3s_indexbuffer = NULL;
11196         rsurface.batchelement3s_bufferoffset = 0;
11197         rsurface.passcolor4f = NULL;
11198         rsurface.passcolor4f_vertexbuffer = NULL;
11199         rsurface.passcolor4f_bufferoffset = 0;
11200
11201         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11202         {
11203                 if ((wantnormals || wanttangents) && !normal3f)
11204                 {
11205                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11206                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11207                 }
11208                 if (wanttangents && !svector3f)
11209                 {
11210                         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);
11211                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11212                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11213                 }
11214         }
11215
11216         // now convert arrays into vertexmesh structs
11217         for (i = 0;i < numvertices;i++)
11218         {
11219                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11220                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11221                 if (rsurface.modelsvector3f)
11222                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11223                 if (rsurface.modeltvector3f)
11224                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11225                 if (rsurface.modelnormal3f)
11226                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11227                 if (rsurface.modellightmapcolor4f)
11228                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11229                 if (rsurface.modeltexcoordtexture2f)
11230                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11231                 if (rsurface.modeltexcoordlightmap2f)
11232                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11233         }
11234 }
11235
11236 float RSurf_FogPoint(const float *v)
11237 {
11238         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11239         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11240         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11241         float FogHeightFade = r_refdef.fogheightfade;
11242         float fogfrac;
11243         unsigned int fogmasktableindex;
11244         if (r_refdef.fogplaneviewabove)
11245                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11246         else
11247                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11248         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11249         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11250 }
11251
11252 float RSurf_FogVertex(const float *v)
11253 {
11254         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11255         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11256         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11257         float FogHeightFade = rsurface.fogheightfade;
11258         float fogfrac;
11259         unsigned int fogmasktableindex;
11260         if (r_refdef.fogplaneviewabove)
11261                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11262         else
11263                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11264         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11265         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11266 }
11267
11268 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11269 {
11270         int i;
11271         for (i = 0;i < numelements;i++)
11272                 outelement3i[i] = inelement3i[i] + adjust;
11273 }
11274
11275 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11276 extern cvar_t gl_vbo;
11277 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11278 {
11279         int deformindex;
11280         int firsttriangle;
11281         int numtriangles;
11282         int firstvertex;
11283         int endvertex;
11284         int numvertices;
11285         int surfacefirsttriangle;
11286         int surfacenumtriangles;
11287         int surfacefirstvertex;
11288         int surfaceendvertex;
11289         int surfacenumvertices;
11290         int surfaceadjustvertex;
11291         int needsupdate;
11292         int i, j;
11293         qboolean gaps;
11294         qboolean dynamicvertex;
11295         float amplitude;
11296         float animpos;
11297         float scale;
11298         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11299         float waveparms[4];
11300         q3shaderinfo_deform_t *deform;
11301         const msurface_t *surface, *firstsurface;
11302         r_vertexposition_t *vertexposition;
11303         r_vertexmesh_t *vertexmesh;
11304         if (!texturenumsurfaces)
11305                 return;
11306         // find vertex range of this surface batch
11307         gaps = false;
11308         firstsurface = texturesurfacelist[0];
11309         firsttriangle = firstsurface->num_firsttriangle;
11310         numtriangles = 0;
11311         firstvertex = endvertex = firstsurface->num_firstvertex;
11312         for (i = 0;i < texturenumsurfaces;i++)
11313         {
11314                 surface = texturesurfacelist[i];
11315                 if (surface != firstsurface + i)
11316                         gaps = true;
11317                 surfacefirstvertex = surface->num_firstvertex;
11318                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11319                 surfacenumtriangles = surface->num_triangles;
11320                 if (firstvertex > surfacefirstvertex)
11321                         firstvertex = surfacefirstvertex;
11322                 if (endvertex < surfaceendvertex)
11323                         endvertex = surfaceendvertex;
11324                 numtriangles += surfacenumtriangles;
11325         }
11326         if (!numtriangles)
11327                 return;
11328
11329         // we now know the vertex range used, and if there are any gaps in it
11330         rsurface.batchfirstvertex = firstvertex;
11331         rsurface.batchnumvertices = endvertex - firstvertex;
11332         rsurface.batchfirsttriangle = firsttriangle;
11333         rsurface.batchnumtriangles = numtriangles;
11334
11335         // this variable holds flags for which properties have been updated that
11336         // may require regenerating vertexmesh or vertexposition arrays...
11337         needsupdate = 0;
11338
11339         // check if any dynamic vertex processing must occur
11340         dynamicvertex = false;
11341
11342         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11343                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11344         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11345         {
11346                 switch (deform->deform)
11347                 {
11348                 default:
11349                 case Q3DEFORM_PROJECTIONSHADOW:
11350                 case Q3DEFORM_TEXT0:
11351                 case Q3DEFORM_TEXT1:
11352                 case Q3DEFORM_TEXT2:
11353                 case Q3DEFORM_TEXT3:
11354                 case Q3DEFORM_TEXT4:
11355                 case Q3DEFORM_TEXT5:
11356                 case Q3DEFORM_TEXT6:
11357                 case Q3DEFORM_TEXT7:
11358                 case Q3DEFORM_NONE:
11359                         break;
11360                 case Q3DEFORM_AUTOSPRITE:
11361                         dynamicvertex = true;
11362                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11363                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11364                         break;
11365                 case Q3DEFORM_AUTOSPRITE2:
11366                         dynamicvertex = true;
11367                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11368                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11369                         break;
11370                 case Q3DEFORM_NORMAL:
11371                         dynamicvertex = true;
11372                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11373                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11374                         break;
11375                 case Q3DEFORM_WAVE:
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_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11380                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11381                         break;
11382                 case Q3DEFORM_BULGE:
11383                         dynamicvertex = true;
11384                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11385                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11386                         break;
11387                 case Q3DEFORM_MOVE:
11388                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11389                                 break; // if wavefunc is a nop, ignore this transform
11390                         dynamicvertex = true;
11391                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11392                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11393                         break;
11394                 }
11395         }
11396         switch(rsurface.texture->tcgen.tcgen)
11397         {
11398         default:
11399         case Q3TCGEN_TEXTURE:
11400                 break;
11401         case Q3TCGEN_LIGHTMAP:
11402                 dynamicvertex = true;
11403                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11404                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11405                 break;
11406         case Q3TCGEN_VECTOR:
11407                 dynamicvertex = true;
11408                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11409                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11410                 break;
11411         case Q3TCGEN_ENVIRONMENT:
11412                 dynamicvertex = true;
11413                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11414                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11415                 break;
11416         }
11417         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11418         {
11419                 dynamicvertex = true;
11420                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11421                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11422         }
11423
11424         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11425         {
11426                 dynamicvertex = true;
11427                 batchneed |= BATCHNEED_NOGAPS;
11428                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11429         }
11430
11431         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11432         {
11433                 dynamicvertex = true;
11434                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11435                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11436         }
11437
11438         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11439         {
11440                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11441                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11442                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11443                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11444                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11445                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11446                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11447         }
11448
11449         // when the model data has no vertex buffer (dynamic mesh), we need to
11450         // eliminate gaps
11451         if (!rsurface.modelvertexmeshbuffer)
11452                 batchneed |= BATCHNEED_NOGAPS;
11453
11454         // if needsupdate, we have to do a dynamic vertex batch for sure
11455         if (needsupdate & batchneed)
11456                 dynamicvertex = true;
11457
11458         // see if we need to build vertexmesh from arrays
11459         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11460                 dynamicvertex = true;
11461
11462         // see if we need to build vertexposition from arrays
11463         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11464                 dynamicvertex = true;
11465
11466         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11467         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11468                 dynamicvertex = true;
11469
11470         // if there is a chance of animated vertex colors, it's a dynamic batch
11471         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11472                 dynamicvertex = true;
11473
11474         rsurface.batchvertex3f = rsurface.modelvertex3f;
11475         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11476         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11477         rsurface.batchsvector3f = rsurface.modelsvector3f;
11478         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11479         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11480         rsurface.batchtvector3f = rsurface.modeltvector3f;
11481         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11482         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11483         rsurface.batchnormal3f = rsurface.modelnormal3f;
11484         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11485         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11486         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11487         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11488         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11489         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11490         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11491         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11492         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11493         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11494         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11495         rsurface.batchvertexposition = rsurface.modelvertexposition;
11496         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11497         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11498         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11499         rsurface.batchelement3i = rsurface.modelelement3i;
11500         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11501         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11502         rsurface.batchelement3s = rsurface.modelelement3s;
11503         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11504         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11505
11506         // if any dynamic vertex processing has to occur in software, we copy the
11507         // entire surface list together before processing to rebase the vertices
11508         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11509         //
11510         // if any gaps exist and we do not have a static vertex buffer, we have to
11511         // copy the surface list together to avoid wasting upload bandwidth on the
11512         // vertices in the gaps.
11513         //
11514         // if gaps exist and we have a static vertex buffer, we still have to
11515         // combine the index buffer ranges into one dynamic index buffer.
11516         //
11517         // in all cases we end up with data that can be drawn in one call.
11518
11519         if (!dynamicvertex)
11520         {
11521                 // static vertex data, just set pointers...
11522                 rsurface.batchgeneratedvertex = false;
11523                 // if there are gaps, we want to build a combined index buffer,
11524                 // otherwise use the original static buffer with an appropriate offset
11525                 if (gaps)
11526                 {
11527                         firsttriangle = 0;
11528                         numtriangles = 0;
11529                         for (i = 0;i < texturenumsurfaces;i++)
11530                         {
11531                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11532                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11533                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11534                                 numtriangles += surfacenumtriangles;
11535                         }
11536                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11537                         rsurface.batchelement3i_indexbuffer = NULL;
11538                         rsurface.batchelement3i_bufferoffset = 0;
11539                         rsurface.batchelement3s = NULL;
11540                         rsurface.batchelement3s_indexbuffer = NULL;
11541                         rsurface.batchelement3s_bufferoffset = 0;
11542                         if (endvertex <= 65536)
11543                         {
11544                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11545                                 for (i = 0;i < numtriangles*3;i++)
11546                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11547                         }
11548                         rsurface.batchfirsttriangle = firsttriangle;
11549                         rsurface.batchnumtriangles = numtriangles;
11550                 }
11551                 return;
11552         }
11553
11554         // something needs software processing, do it for real...
11555         // we only directly handle interleaved array data in this case...
11556         rsurface.batchgeneratedvertex = true;
11557
11558         // now copy the vertex data into a combined array and make an index array
11559         // (this is what Quake3 does all the time)
11560         //if (gaps || rsurface.batchfirstvertex)
11561         {
11562                 rsurface.batchvertexposition = NULL;
11563                 rsurface.batchvertexpositionbuffer = NULL;
11564                 rsurface.batchvertexmesh = NULL;
11565                 rsurface.batchvertexmeshbuffer = NULL;
11566                 rsurface.batchvertex3f = NULL;
11567                 rsurface.batchvertex3f_vertexbuffer = NULL;
11568                 rsurface.batchvertex3f_bufferoffset = 0;
11569                 rsurface.batchsvector3f = NULL;
11570                 rsurface.batchsvector3f_vertexbuffer = NULL;
11571                 rsurface.batchsvector3f_bufferoffset = 0;
11572                 rsurface.batchtvector3f = NULL;
11573                 rsurface.batchtvector3f_vertexbuffer = NULL;
11574                 rsurface.batchtvector3f_bufferoffset = 0;
11575                 rsurface.batchnormal3f = NULL;
11576                 rsurface.batchnormal3f_vertexbuffer = NULL;
11577                 rsurface.batchnormal3f_bufferoffset = 0;
11578                 rsurface.batchlightmapcolor4f = NULL;
11579                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11580                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11581                 rsurface.batchtexcoordtexture2f = NULL;
11582                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11583                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11584                 rsurface.batchtexcoordlightmap2f = NULL;
11585                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11586                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11587                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11588                 rsurface.batchelement3i_indexbuffer = NULL;
11589                 rsurface.batchelement3i_bufferoffset = 0;
11590                 rsurface.batchelement3s = NULL;
11591                 rsurface.batchelement3s_indexbuffer = NULL;
11592                 rsurface.batchelement3s_bufferoffset = 0;
11593                 // we'll only be setting up certain arrays as needed
11594                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11595                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11596                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11597                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11598                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11599                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11600                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11601                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11602                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11603                 {
11604                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11605                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11606                 }
11607                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11608                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11609                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11610                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11611                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11612                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11613                 numvertices = 0;
11614                 numtriangles = 0;
11615                 for (i = 0;i < texturenumsurfaces;i++)
11616                 {
11617                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11618                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11619                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11620                         surfaceadjustvertex = numvertices - surfacefirstvertex;
11621                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11622                         // copy only the data requested
11623                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11624                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11625                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11626                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11627                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11628                         {
11629                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11630                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11631                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11632                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11633                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11634                                 {
11635                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11636                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11637                                 }
11638                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11639                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11640                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11641                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11642                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11643                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11644                         }
11645                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11646                         numvertices += surfacenumvertices;
11647                         numtriangles += surfacenumtriangles;
11648                 }
11649
11650                 // generate a 16bit index array as well if possible
11651                 // (in general, dynamic batches fit)
11652                 if (numvertices <= 65536)
11653                 {
11654                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11655                         for (i = 0;i < numtriangles*3;i++)
11656                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11657                 }
11658
11659                 // since we've copied everything, the batch now starts at 0
11660                 rsurface.batchfirstvertex = 0;
11661                 rsurface.batchnumvertices = numvertices;
11662                 rsurface.batchfirsttriangle = 0;
11663                 rsurface.batchnumtriangles = numtriangles;
11664         }
11665
11666         // q1bsp surfaces rendered in vertex color mode have to have colors
11667         // calculated based on lightstyles
11668         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11669         {
11670                 // generate color arrays for the surfaces in this list
11671                 int c[4];
11672                 int scale;
11673                 int size3;
11674                 const int *offsets;
11675                 const unsigned char *lm;
11676                 numvertices = 0;
11677                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11678                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11679                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11680                 for (i = 0;i < texturenumsurfaces;i++)
11681                 {
11682                         surface = texturesurfacelist[i];
11683                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11684                         surfacenumvertices = surface->num_vertices;
11685                         if (surface->lightmapinfo->samples)
11686                         {
11687                                 for (j = 0;j < surfacenumvertices;j++)
11688                                 {
11689                                         lm = surface->lightmapinfo->samples + offsets[j];
11690                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11691                                         VectorScale(lm, scale, c);
11692                                         if (surface->lightmapinfo->styles[1] != 255)
11693                                         {
11694                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11695                                                 lm += size3;
11696                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11697                                                 VectorMA(c, scale, lm, c);
11698                                                 if (surface->lightmapinfo->styles[2] != 255)
11699                                                 {
11700                                                         lm += size3;
11701                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11702                                                         VectorMA(c, scale, lm, c);
11703                                                         if (surface->lightmapinfo->styles[3] != 255)
11704                                                         {
11705                                                                 lm += size3;
11706                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11707                                                                 VectorMA(c, scale, lm, c);
11708                                                         }
11709                                                 }
11710                                         }
11711                                         c[0] >>= 15;
11712                                         c[1] >>= 15;
11713                                         c[2] >>= 15;
11714                                         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);
11715                                         numvertices++;
11716                                 }
11717                         }
11718                         else
11719                         {
11720                                 for (j = 0;j < surfacenumvertices;j++)
11721                                 {
11722                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11723                                         numvertices++;
11724                                 }
11725                         }
11726                 }
11727         }
11728
11729         // if vertices are deformed (sprite flares and things in maps, possibly
11730         // water waves, bulges and other deformations), modify the copied vertices
11731         // in place
11732         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11733         {
11734                 switch (deform->deform)
11735                 {
11736                 default:
11737                 case Q3DEFORM_PROJECTIONSHADOW:
11738                 case Q3DEFORM_TEXT0:
11739                 case Q3DEFORM_TEXT1:
11740                 case Q3DEFORM_TEXT2:
11741                 case Q3DEFORM_TEXT3:
11742                 case Q3DEFORM_TEXT4:
11743                 case Q3DEFORM_TEXT5:
11744                 case Q3DEFORM_TEXT6:
11745                 case Q3DEFORM_TEXT7:
11746                 case Q3DEFORM_NONE:
11747                         break;
11748                 case Q3DEFORM_AUTOSPRITE:
11749                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11750                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11751                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11752                         VectorNormalize(newforward);
11753                         VectorNormalize(newright);
11754                         VectorNormalize(newup);
11755                         // a single autosprite surface can contain multiple sprites...
11756                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11757                         {
11758                                 VectorClear(center);
11759                                 for (i = 0;i < 4;i++)
11760                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11761                                 VectorScale(center, 0.25f, center);
11762                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11763                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11764                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11765                                 for (i = 0;i < 4;i++)
11766                                 {
11767                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11768                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11769                                 }
11770                         }
11771                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11772                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11773                         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);
11774                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11775                         rsurface.batchvertex3f_vertexbuffer = NULL;
11776                         rsurface.batchvertex3f_bufferoffset = 0;
11777                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11778                         rsurface.batchsvector3f_vertexbuffer = NULL;
11779                         rsurface.batchsvector3f_bufferoffset = 0;
11780                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11781                         rsurface.batchtvector3f_vertexbuffer = NULL;
11782                         rsurface.batchtvector3f_bufferoffset = 0;
11783                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11784                         rsurface.batchnormal3f_vertexbuffer = NULL;
11785                         rsurface.batchnormal3f_bufferoffset = 0;
11786                         break;
11787                 case Q3DEFORM_AUTOSPRITE2:
11788                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11789                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11790                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11791                         VectorNormalize(newforward);
11792                         VectorNormalize(newright);
11793                         VectorNormalize(newup);
11794                         {
11795                                 const float *v1, *v2;
11796                                 vec3_t start, end;
11797                                 float f, l;
11798                                 struct
11799                                 {
11800                                         float length2;
11801                                         const float *v1;
11802                                         const float *v2;
11803                                 }
11804                                 shortest[2];
11805                                 memset(shortest, 0, sizeof(shortest));
11806                                 // a single autosprite surface can contain multiple sprites...
11807                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11808                                 {
11809                                         VectorClear(center);
11810                                         for (i = 0;i < 4;i++)
11811                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11812                                         VectorScale(center, 0.25f, center);
11813                                         // find the two shortest edges, then use them to define the
11814                                         // axis vectors for rotating around the central axis
11815                                         for (i = 0;i < 6;i++)
11816                                         {
11817                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11818                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11819                                                 l = VectorDistance2(v1, v2);
11820                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11821                                                 if (v1[2] != v2[2])
11822                                                         l += (1.0f / 1024.0f);
11823                                                 if (shortest[0].length2 > l || i == 0)
11824                                                 {
11825                                                         shortest[1] = shortest[0];
11826                                                         shortest[0].length2 = l;
11827                                                         shortest[0].v1 = v1;
11828                                                         shortest[0].v2 = v2;
11829                                                 }
11830                                                 else if (shortest[1].length2 > l || i == 1)
11831                                                 {
11832                                                         shortest[1].length2 = l;
11833                                                         shortest[1].v1 = v1;
11834                                                         shortest[1].v2 = v2;
11835                                                 }
11836                                         }
11837                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11838                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11839                                         // this calculates the right vector from the shortest edge
11840                                         // and the up vector from the edge midpoints
11841                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11842                                         VectorNormalize(right);
11843                                         VectorSubtract(end, start, up);
11844                                         VectorNormalize(up);
11845                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11846                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11847                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11848                                         VectorNegate(forward, forward);
11849                                         VectorReflect(forward, 0, up, forward);
11850                                         VectorNormalize(forward);
11851                                         CrossProduct(up, forward, newright);
11852                                         VectorNormalize(newright);
11853                                         // rotate the quad around the up axis vector, this is made
11854                                         // especially easy by the fact we know the quad is flat,
11855                                         // so we only have to subtract the center position and
11856                                         // measure distance along the right vector, and then
11857                                         // multiply that by the newright vector and add back the
11858                                         // center position
11859                                         // we also need to subtract the old position to undo the
11860                                         // displacement from the center, which we do with a
11861                                         // DotProduct, the subtraction/addition of center is also
11862                                         // optimized into DotProducts here
11863                                         l = DotProduct(right, center);
11864                                         for (i = 0;i < 4;i++)
11865                                         {
11866                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11867                                                 f = DotProduct(right, v1) - l;
11868                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11869                                         }
11870                                 }
11871                         }
11872                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11873                         rsurface.batchvertex3f_vertexbuffer = NULL;
11874                         rsurface.batchvertex3f_bufferoffset = 0;
11875                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11876                         {
11877                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11878                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11879                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11880                                 rsurface.batchnormal3f_bufferoffset = 0;
11881                         }
11882                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11883                         {
11884                                 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);
11885                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11886                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11887                                 rsurface.batchsvector3f_bufferoffset = 0;
11888                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11889                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11890                                 rsurface.batchtvector3f_bufferoffset = 0;
11891                         }
11892                         break;
11893                 case Q3DEFORM_NORMAL:
11894                         // deform the normals to make reflections wavey
11895                         for (j = 0;j < rsurface.batchnumvertices;j++)
11896                         {
11897                                 float vertex[3];
11898                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11899                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11900                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11901                                 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]);
11902                                 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]);
11903                                 VectorNormalize(normal);
11904                         }
11905                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11906                         rsurface.batchnormal3f_vertexbuffer = NULL;
11907                         rsurface.batchnormal3f_bufferoffset = 0;
11908                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11909                         {
11910                                 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);
11911                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11912                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11913                                 rsurface.batchsvector3f_bufferoffset = 0;
11914                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11915                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11916                                 rsurface.batchtvector3f_bufferoffset = 0;
11917                         }
11918                         break;
11919                 case Q3DEFORM_WAVE:
11920                         // deform vertex array to make wavey water and flags and such
11921                         waveparms[0] = deform->waveparms[0];
11922                         waveparms[1] = deform->waveparms[1];
11923                         waveparms[2] = deform->waveparms[2];
11924                         waveparms[3] = deform->waveparms[3];
11925                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11926                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11927                         // this is how a divisor of vertex influence on deformation
11928                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11929                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11930                         for (j = 0;j < rsurface.batchnumvertices;j++)
11931                         {
11932                                 // if the wavefunc depends on time, evaluate it per-vertex
11933                                 if (waveparms[3])
11934                                 {
11935                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11936                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11937                                 }
11938                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11939                         }
11940                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11941                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11942                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11943                         rsurface.batchvertex3f_vertexbuffer = NULL;
11944                         rsurface.batchvertex3f_bufferoffset = 0;
11945                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11946                         rsurface.batchnormal3f_vertexbuffer = NULL;
11947                         rsurface.batchnormal3f_bufferoffset = 0;
11948                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11949                         {
11950                                 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);
11951                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11952                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11953                                 rsurface.batchsvector3f_bufferoffset = 0;
11954                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11955                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11956                                 rsurface.batchtvector3f_bufferoffset = 0;
11957                         }
11958                         break;
11959                 case Q3DEFORM_BULGE:
11960                         // deform vertex array to make the surface have moving bulges
11961                         for (j = 0;j < rsurface.batchnumvertices;j++)
11962                         {
11963                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11964                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11965                         }
11966                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11967                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11968                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11969                         rsurface.batchvertex3f_vertexbuffer = NULL;
11970                         rsurface.batchvertex3f_bufferoffset = 0;
11971                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11972                         rsurface.batchnormal3f_vertexbuffer = NULL;
11973                         rsurface.batchnormal3f_bufferoffset = 0;
11974                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11975                         {
11976                                 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);
11977                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11978                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11979                                 rsurface.batchsvector3f_bufferoffset = 0;
11980                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11981                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11982                                 rsurface.batchtvector3f_bufferoffset = 0;
11983                         }
11984                         break;
11985                 case Q3DEFORM_MOVE:
11986                         // deform vertex array
11987                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11988                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11989                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11990                         VectorScale(deform->parms, scale, waveparms);
11991                         for (j = 0;j < rsurface.batchnumvertices;j++)
11992                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11993                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11994                         rsurface.batchvertex3f_vertexbuffer = NULL;
11995                         rsurface.batchvertex3f_bufferoffset = 0;
11996                         break;
11997                 }
11998         }
11999
12000         // generate texcoords based on the chosen texcoord source
12001         switch(rsurface.texture->tcgen.tcgen)
12002         {
12003         default:
12004         case Q3TCGEN_TEXTURE:
12005                 break;
12006         case Q3TCGEN_LIGHTMAP:
12007                 if (rsurface.batchtexcoordlightmap2f)
12008                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12009                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12010                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12011                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12012                 break;
12013         case Q3TCGEN_VECTOR:
12014                 for (j = 0;j < rsurface.batchnumvertices;j++)
12015                 {
12016                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12017                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12018                 }
12019                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12020                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12021                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12022                 break;
12023         case Q3TCGEN_ENVIRONMENT:
12024                 // make environment reflections using a spheremap
12025                 for (j = 0;j < rsurface.batchnumvertices;j++)
12026                 {
12027                         // identical to Q3A's method, but executed in worldspace so
12028                         // carried models can be shiny too
12029
12030                         float viewer[3], d, reflected[3], worldreflected[3];
12031
12032                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12033                         // VectorNormalize(viewer);
12034
12035                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12036
12037                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12038                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12039                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12040                         // note: this is proportinal to viewer, so we can normalize later
12041
12042                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12043                         VectorNormalize(worldreflected);
12044
12045                         // note: this sphere map only uses world x and z!
12046                         // so positive and negative y will LOOK THE SAME.
12047                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12048                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12049                 }
12050                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12051                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12052                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12053                 break;
12054         }
12055         // the only tcmod that needs software vertex processing is turbulent, so
12056         // check for it here and apply the changes if needed
12057         // and we only support that as the first one
12058         // (handling a mixture of turbulent and other tcmods would be problematic
12059         //  without punting it entirely to a software path)
12060         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12061         {
12062                 amplitude = rsurface.texture->tcmods[0].parms[1];
12063                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12064                 for (j = 0;j < rsurface.batchnumvertices;j++)
12065                 {
12066                         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);
12067                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12068                 }
12069                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12070                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12071                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12072         }
12073
12074         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12075         {
12076                 // convert the modified arrays to vertex structs
12077                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12078                 rsurface.batchvertexmeshbuffer = NULL;
12079                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12080                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12081                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12082                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12083                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12084                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12085                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12086                 {
12087                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12088                         {
12089                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12090                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12091                         }
12092                 }
12093                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12094                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12095                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12096                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12097                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12098                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12099                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12100                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12101                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12102         }
12103
12104         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12105         {
12106                 // convert the modified arrays to vertex structs
12107                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12108                 rsurface.batchvertexpositionbuffer = NULL;
12109                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12110                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12111                 else
12112                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12113                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12114         }
12115 }
12116
12117 void RSurf_DrawBatch(void)
12118 {
12119         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);
12120 }
12121
12122 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12123 {
12124         // pick the closest matching water plane
12125         int planeindex, vertexindex, bestplaneindex = -1;
12126         float d, bestd;
12127         vec3_t vert;
12128         const float *v;
12129         r_waterstate_waterplane_t *p;
12130         bestd = 0;
12131         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12132         {
12133                 if(p->camera_entity != rsurface.texture->camera_entity)
12134                         continue;
12135                 d = 0;
12136                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12137                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12138                 {
12139                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12140                         d += fabs(PlaneDiff(vert, &p->plane));
12141                 }
12142                 if (bestd > d || bestplaneindex < 0)
12143                 {
12144                         bestd = d;
12145                         bestplaneindex = planeindex;
12146                 }
12147         }
12148         return bestplaneindex;
12149 }
12150
12151 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12152 {
12153         int i;
12154         for (i = 0;i < rsurface.batchnumvertices;i++)
12155                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12156         rsurface.passcolor4f = rsurface.array_passcolor4f;
12157         rsurface.passcolor4f_vertexbuffer = 0;
12158         rsurface.passcolor4f_bufferoffset = 0;
12159 }
12160
12161 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12162 {
12163         int i;
12164         float f;
12165         const float *v;
12166         const float *c;
12167         float *c2;
12168         if (rsurface.passcolor4f)
12169         {
12170                 // generate color arrays
12171                 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)
12172                 {
12173                         f = RSurf_FogVertex(v);
12174                         c2[0] = c[0] * f;
12175                         c2[1] = c[1] * f;
12176                         c2[2] = c[2] * f;
12177                         c2[3] = c[3];
12178                 }
12179         }
12180         else
12181         {
12182                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12183                 {
12184                         f = RSurf_FogVertex(v);
12185                         c2[0] = f;
12186                         c2[1] = f;
12187                         c2[2] = f;
12188                         c2[3] = 1;
12189                 }
12190         }
12191         rsurface.passcolor4f = rsurface.array_passcolor4f;
12192         rsurface.passcolor4f_vertexbuffer = 0;
12193         rsurface.passcolor4f_bufferoffset = 0;
12194 }
12195
12196 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12197 {
12198         int i;
12199         float f;
12200         const float *v;
12201         const float *c;
12202         float *c2;
12203         if (!rsurface.passcolor4f)
12204                 return;
12205         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)
12206         {
12207                 f = RSurf_FogVertex(v);
12208                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12209                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12210                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12211                 c2[3] = c[3];
12212         }
12213         rsurface.passcolor4f = rsurface.array_passcolor4f;
12214         rsurface.passcolor4f_vertexbuffer = 0;
12215         rsurface.passcolor4f_bufferoffset = 0;
12216 }
12217
12218 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12219 {
12220         int i;
12221         const float *c;
12222         float *c2;
12223         if (!rsurface.passcolor4f)
12224                 return;
12225         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12226         {
12227                 c2[0] = c[0] * r;
12228                 c2[1] = c[1] * g;
12229                 c2[2] = c[2] * b;
12230                 c2[3] = c[3] * a;
12231         }
12232         rsurface.passcolor4f = rsurface.array_passcolor4f;
12233         rsurface.passcolor4f_vertexbuffer = 0;
12234         rsurface.passcolor4f_bufferoffset = 0;
12235 }
12236
12237 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12238 {
12239         int i;
12240         const float *c;
12241         float *c2;
12242         if (!rsurface.passcolor4f)
12243                 return;
12244         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12245         {
12246                 c2[0] = c[0] + r_refdef.scene.ambient;
12247                 c2[1] = c[1] + r_refdef.scene.ambient;
12248                 c2[2] = c[2] + r_refdef.scene.ambient;
12249                 c2[3] = c[3];
12250         }
12251         rsurface.passcolor4f = rsurface.array_passcolor4f;
12252         rsurface.passcolor4f_vertexbuffer = 0;
12253         rsurface.passcolor4f_bufferoffset = 0;
12254 }
12255
12256 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12257 {
12258         // TODO: optimize
12259         rsurface.passcolor4f = NULL;
12260         rsurface.passcolor4f_vertexbuffer = 0;
12261         rsurface.passcolor4f_bufferoffset = 0;
12262         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12263         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12264         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12265         GL_Color(r, g, b, a);
12266         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12267         RSurf_DrawBatch();
12268 }
12269
12270 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12271 {
12272         // TODO: optimize applyfog && applycolor case
12273         // just apply fog if necessary, and tint the fog color array if necessary
12274         rsurface.passcolor4f = NULL;
12275         rsurface.passcolor4f_vertexbuffer = 0;
12276         rsurface.passcolor4f_bufferoffset = 0;
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_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12285 {
12286         // TODO: optimize
12287         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12288         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12289         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12290         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12291         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12292         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12293         GL_Color(r, g, b, a);
12294         RSurf_DrawBatch();
12295 }
12296
12297 static void RSurf_DrawBatch_GL11_ClampColor(void)
12298 {
12299         int i;
12300         const float *c1;
12301         float *c2;
12302         if (!rsurface.passcolor4f)
12303                 return;
12304         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12305         {
12306                 c2[0] = bound(0.0f, c1[0], 1.0f);
12307                 c2[1] = bound(0.0f, c1[1], 1.0f);
12308                 c2[2] = bound(0.0f, c1[2], 1.0f);
12309                 c2[3] = bound(0.0f, c1[3], 1.0f);
12310         }
12311 }
12312
12313 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12314 {
12315         int i;
12316         float f;
12317         float alpha;
12318         const float *v;
12319         const float *n;
12320         float *c;
12321         vec3_t ambientcolor;
12322         vec3_t diffusecolor;
12323         vec3_t lightdir;
12324         // TODO: optimize
12325         // model lighting
12326         VectorCopy(rsurface.modellight_lightdir, lightdir);
12327         f = 0.5f * r_refdef.lightmapintensity;
12328         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12329         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12330         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12331         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12332         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12333         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12334         alpha = *a;
12335         if (VectorLength2(diffusecolor) > 0)
12336         {
12337                 // q3-style directional shading
12338                 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)
12339                 {
12340                         if ((f = DotProduct(n, lightdir)) > 0)
12341                                 VectorMA(ambientcolor, f, diffusecolor, c);
12342                         else
12343                                 VectorCopy(ambientcolor, c);
12344                         c[3] = alpha;
12345                 }
12346                 *r = 1;
12347                 *g = 1;
12348                 *b = 1;
12349                 *a = 1;
12350                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12351                 rsurface.passcolor4f_vertexbuffer = 0;
12352                 rsurface.passcolor4f_bufferoffset = 0;
12353                 *applycolor = false;
12354         }
12355         else
12356         {
12357                 *r = ambientcolor[0];
12358                 *g = ambientcolor[1];
12359                 *b = ambientcolor[2];
12360                 rsurface.passcolor4f = NULL;
12361                 rsurface.passcolor4f_vertexbuffer = 0;
12362                 rsurface.passcolor4f_bufferoffset = 0;
12363         }
12364 }
12365
12366 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12367 {
12368         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12369         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12370         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12371         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12372         GL_Color(r, g, b, a);
12373         RSurf_DrawBatch();
12374 }
12375
12376 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12377 {
12378         int i;
12379         float f;
12380         const float *v;
12381         float *c;
12382         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12383         {
12384                 f = 1 - RSurf_FogVertex(v);
12385                 c[0] = r;
12386                 c[1] = g;
12387                 c[2] = b;
12388                 c[3] = f * a;
12389         }
12390 }
12391
12392 void RSurf_SetupDepthAndCulling(void)
12393 {
12394         // submodels are biased to avoid z-fighting with world surfaces that they
12395         // may be exactly overlapping (avoids z-fighting artifacts on certain
12396         // doors and things in Quake maps)
12397         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12398         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12399         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12400         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12401 }
12402
12403 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12404 {
12405         // transparent sky would be ridiculous
12406         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12407                 return;
12408         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12409         skyrenderlater = true;
12410         RSurf_SetupDepthAndCulling();
12411         GL_DepthMask(true);
12412         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12413         // skymasking on them, and Quake3 never did sky masking (unlike
12414         // software Quake and software Quake2), so disable the sky masking
12415         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12416         // and skymasking also looks very bad when noclipping outside the
12417         // level, so don't use it then either.
12418         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12419         {
12420                 R_Mesh_ResetTextureState();
12421                 if (skyrendermasked)
12422                 {
12423                         R_SetupShader_DepthOrShadow();
12424                         // depth-only (masking)
12425                         GL_ColorMask(0,0,0,0);
12426                         // just to make sure that braindead drivers don't draw
12427                         // anything despite that colormask...
12428                         GL_BlendFunc(GL_ZERO, GL_ONE);
12429                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12430                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12431                 }
12432                 else
12433                 {
12434                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12435                         // fog sky
12436                         GL_BlendFunc(GL_ONE, GL_ZERO);
12437                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12438                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12439                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12440                 }
12441                 RSurf_DrawBatch();
12442                 if (skyrendermasked)
12443                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12444         }
12445         R_Mesh_ResetTextureState();
12446         GL_Color(1, 1, 1, 1);
12447 }
12448
12449 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12450 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12451 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12452 {
12453         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12454                 return;
12455         if (prepass)
12456         {
12457                 // render screenspace normalmap to texture
12458                 GL_DepthMask(true);
12459                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12460                 RSurf_DrawBatch();
12461                 return;
12462         }
12463
12464         // bind lightmap texture
12465
12466         // water/refraction/reflection/camera surfaces have to be handled specially
12467         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12468         {
12469                 int start, end, startplaneindex;
12470                 for (start = 0;start < texturenumsurfaces;start = end)
12471                 {
12472                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12473                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12474                                 ;
12475                         // now that we have a batch using the same planeindex, render it
12476                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12477                         {
12478                                 // render water or distortion background
12479                                 GL_DepthMask(true);
12480                                 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));
12481                                 RSurf_DrawBatch();
12482                                 // blend surface on top
12483                                 GL_DepthMask(false);
12484                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12485                                 RSurf_DrawBatch();
12486                         }
12487                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12488                         {
12489                                 // render surface with reflection texture as input
12490                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12491                                 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));
12492                                 RSurf_DrawBatch();
12493                         }
12494                 }
12495                 return;
12496         }
12497
12498         // render surface batch normally
12499         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12500         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12501         RSurf_DrawBatch();
12502 }
12503
12504 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12505 {
12506         // OpenGL 1.3 path - anything not completely ancient
12507         qboolean applycolor;
12508         qboolean applyfog;
12509         int layerindex;
12510         const texturelayer_t *layer;
12511         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);
12512         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12513
12514         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12515         {
12516                 vec4_t layercolor;
12517                 int layertexrgbscale;
12518                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12519                 {
12520                         if (layerindex == 0)
12521                                 GL_AlphaTest(true);
12522                         else
12523                         {
12524                                 GL_AlphaTest(false);
12525                                 GL_DepthFunc(GL_EQUAL);
12526                         }
12527                 }
12528                 GL_DepthMask(layer->depthmask && writedepth);
12529                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12530                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12531                 {
12532                         layertexrgbscale = 4;
12533                         VectorScale(layer->color, 0.25f, layercolor);
12534                 }
12535                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12536                 {
12537                         layertexrgbscale = 2;
12538                         VectorScale(layer->color, 0.5f, layercolor);
12539                 }
12540                 else
12541                 {
12542                         layertexrgbscale = 1;
12543                         VectorScale(layer->color, 1.0f, layercolor);
12544                 }
12545                 layercolor[3] = layer->color[3];
12546                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12547                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12548                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12549                 switch (layer->type)
12550                 {
12551                 case TEXTURELAYERTYPE_LITTEXTURE:
12552                         // single-pass lightmapped texture with 2x rgbscale
12553                         R_Mesh_TexBind(0, r_texture_white);
12554                         R_Mesh_TexMatrix(0, NULL);
12555                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12556                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12557                         R_Mesh_TexBind(1, layer->texture);
12558                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12559                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12560                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12561                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12562                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12563                         else if (rsurface.uselightmaptexture)
12564                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12565                         else
12566                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12567                         break;
12568                 case TEXTURELAYERTYPE_TEXTURE:
12569                         // singletexture unlit texture with transparency support
12570                         R_Mesh_TexBind(0, layer->texture);
12571                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12572                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12573                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12574                         R_Mesh_TexBind(1, 0);
12575                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12576                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12577                         break;
12578                 case TEXTURELAYERTYPE_FOG:
12579                         // singletexture fogging
12580                         if (layer->texture)
12581                         {
12582                                 R_Mesh_TexBind(0, layer->texture);
12583                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12584                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12585                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12586                         }
12587                         else
12588                         {
12589                                 R_Mesh_TexBind(0, 0);
12590                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12591                         }
12592                         R_Mesh_TexBind(1, 0);
12593                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12594                         // generate a color array for the fog pass
12595                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12596                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12597                         RSurf_DrawBatch();
12598                         break;
12599                 default:
12600                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12601                 }
12602         }
12603         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12604         {
12605                 GL_DepthFunc(GL_LEQUAL);
12606                 GL_AlphaTest(false);
12607         }
12608 }
12609
12610 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12611 {
12612         // OpenGL 1.1 - crusty old voodoo path
12613         qboolean applyfog;
12614         int layerindex;
12615         const texturelayer_t *layer;
12616         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);
12617         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12618
12619         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12620         {
12621                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12622                 {
12623                         if (layerindex == 0)
12624                                 GL_AlphaTest(true);
12625                         else
12626                         {
12627                                 GL_AlphaTest(false);
12628                                 GL_DepthFunc(GL_EQUAL);
12629                         }
12630                 }
12631                 GL_DepthMask(layer->depthmask && writedepth);
12632                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12633                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12634                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12635                 switch (layer->type)
12636                 {
12637                 case TEXTURELAYERTYPE_LITTEXTURE:
12638                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12639                         {
12640                                 // two-pass lit texture with 2x rgbscale
12641                                 // first the lightmap pass
12642                                 R_Mesh_TexBind(0, r_texture_white);
12643                                 R_Mesh_TexMatrix(0, NULL);
12644                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12645                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12646                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12647                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12648                                 else if (rsurface.uselightmaptexture)
12649                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12650                                 else
12651                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12652                                 // then apply the texture to it
12653                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12654                                 R_Mesh_TexBind(0, layer->texture);
12655                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12656                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12657                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12658                                 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);
12659                         }
12660                         else
12661                         {
12662                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12663                                 R_Mesh_TexBind(0, layer->texture);
12664                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12665                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12666                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12667                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12668                                         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);
12669                                 else
12670                                         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);
12671                         }
12672                         break;
12673                 case TEXTURELAYERTYPE_TEXTURE:
12674                         // singletexture unlit texture with transparency support
12675                         R_Mesh_TexBind(0, layer->texture);
12676                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12677                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12678                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12679                         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);
12680                         break;
12681                 case TEXTURELAYERTYPE_FOG:
12682                         // singletexture fogging
12683                         if (layer->texture)
12684                         {
12685                                 R_Mesh_TexBind(0, layer->texture);
12686                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12687                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12688                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12689                         }
12690                         else
12691                         {
12692                                 R_Mesh_TexBind(0, 0);
12693                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12694                         }
12695                         // generate a color array for the fog pass
12696                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12697                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12698                         RSurf_DrawBatch();
12699                         break;
12700                 default:
12701                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12702                 }
12703         }
12704         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12705         {
12706                 GL_DepthFunc(GL_LEQUAL);
12707                 GL_AlphaTest(false);
12708         }
12709 }
12710
12711 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12712 {
12713         int vi;
12714         int j;
12715         r_vertexgeneric_t *batchvertex;
12716         float c[4];
12717
12718         GL_AlphaTest(false);
12719         R_Mesh_ResetTextureState();
12720         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12721
12722         if(rsurface.texture && rsurface.texture->currentskinframe)
12723         {
12724                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12725                 c[3] *= rsurface.texture->currentalpha;
12726         }
12727         else
12728         {
12729                 c[0] = 1;
12730                 c[1] = 0;
12731                 c[2] = 1;
12732                 c[3] = 1;
12733         }
12734
12735         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12736         {
12737                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12738                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12739                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12740         }
12741
12742         // brighten it up (as texture value 127 means "unlit")
12743         c[0] *= 2 * r_refdef.view.colorscale;
12744         c[1] *= 2 * r_refdef.view.colorscale;
12745         c[2] *= 2 * r_refdef.view.colorscale;
12746
12747         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12748                 c[3] *= r_wateralpha.value;
12749
12750         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12751         {
12752                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12753                 GL_DepthMask(false);
12754         }
12755         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12756         {
12757                 GL_BlendFunc(GL_ONE, GL_ONE);
12758                 GL_DepthMask(false);
12759         }
12760         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12761         {
12762                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12763                 GL_DepthMask(false);
12764         }
12765         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12766         {
12767                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12768                 GL_DepthMask(false);
12769         }
12770         else
12771         {
12772                 GL_BlendFunc(GL_ONE, GL_ZERO);
12773                 GL_DepthMask(writedepth);
12774         }
12775
12776         if (r_showsurfaces.integer == 3)
12777         {
12778                 rsurface.passcolor4f = NULL;
12779
12780                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12781                 {
12782                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12783
12784                         rsurface.passcolor4f = NULL;
12785                         rsurface.passcolor4f_vertexbuffer = 0;
12786                         rsurface.passcolor4f_bufferoffset = 0;
12787                 }
12788                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12789                 {
12790                         qboolean applycolor = true;
12791                         float one = 1.0;
12792
12793                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12794
12795                         r_refdef.lightmapintensity = 1;
12796                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12797                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12798                 }
12799                 else
12800                 {
12801                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12802
12803                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12804                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12805                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12806                 }
12807
12808                 if(!rsurface.passcolor4f)
12809                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12810
12811                 RSurf_DrawBatch_GL11_ApplyAmbient();
12812                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12813                 if(r_refdef.fogenabled)
12814                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12815                 RSurf_DrawBatch_GL11_ClampColor();
12816
12817                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12818                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12819                 RSurf_DrawBatch();
12820         }
12821         else if (!r_refdef.view.showdebug)
12822         {
12823                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12824                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12825                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12826                 {
12827                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12828                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12829                 }
12830                 R_Mesh_PrepareVertices_Generic_Unlock();
12831                 RSurf_DrawBatch();
12832         }
12833         else if (r_showsurfaces.integer == 4)
12834         {
12835                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12836                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12837                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12838                 {
12839                         unsigned char c = vi << 3;
12840                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12841                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12842                 }
12843                 R_Mesh_PrepareVertices_Generic_Unlock();
12844                 RSurf_DrawBatch();
12845         }
12846         else if (r_showsurfaces.integer == 2)
12847         {
12848                 const int *e;
12849                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12850                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12851                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12852                 {
12853                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12854                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12855                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12856                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12857                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12858                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12859                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12860                 }
12861                 R_Mesh_PrepareVertices_Generic_Unlock();
12862                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12863         }
12864         else
12865         {
12866                 int texturesurfaceindex;
12867                 int k;
12868                 const msurface_t *surface;
12869                 unsigned char surfacecolor4ub[4];
12870                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12871                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12872                 vi = 0;
12873                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12874                 {
12875                         surface = texturesurfacelist[texturesurfaceindex];
12876                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12877                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12878                         for (j = 0;j < surface->num_vertices;j++)
12879                         {
12880                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12881                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12882                                 vi++;
12883                         }
12884                 }
12885                 R_Mesh_PrepareVertices_Generic_Unlock();
12886                 RSurf_DrawBatch();
12887         }
12888 }
12889
12890 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12891 {
12892         CHECKGLERROR
12893         RSurf_SetupDepthAndCulling();
12894         if (r_showsurfaces.integer)
12895         {
12896                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12897                 return;
12898         }
12899         switch (vid.renderpath)
12900         {
12901         case RENDERPATH_GL20:
12902         case RENDERPATH_CGGL:
12903         case RENDERPATH_D3D9:
12904         case RENDERPATH_D3D10:
12905         case RENDERPATH_D3D11:
12906                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12907                 break;
12908         case RENDERPATH_GL13:
12909                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12910                 break;
12911         case RENDERPATH_GL11:
12912                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12913                 break;
12914         }
12915         CHECKGLERROR
12916 }
12917
12918 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12919 {
12920         CHECKGLERROR
12921         RSurf_SetupDepthAndCulling();
12922         if (r_showsurfaces.integer)
12923         {
12924                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12925                 return;
12926         }
12927         switch (vid.renderpath)
12928         {
12929         case RENDERPATH_GL20:
12930         case RENDERPATH_CGGL:
12931         case RENDERPATH_D3D9:
12932         case RENDERPATH_D3D10:
12933         case RENDERPATH_D3D11:
12934                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12935                 break;
12936         case RENDERPATH_GL13:
12937                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12938                 break;
12939         case RENDERPATH_GL11:
12940                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12941                 break;
12942         }
12943         CHECKGLERROR
12944 }
12945
12946 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12947 {
12948         int i, j;
12949         int texturenumsurfaces, endsurface;
12950         texture_t *texture;
12951         const msurface_t *surface;
12952 #define MAXBATCH_TRANSPARENTSURFACES 256
12953         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12954
12955         // if the model is static it doesn't matter what value we give for
12956         // wantnormals and wanttangents, so this logic uses only rules applicable
12957         // to a model, knowing that they are meaningless otherwise
12958         if (ent == r_refdef.scene.worldentity)
12959                 RSurf_ActiveWorldEntity();
12960         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12961                 RSurf_ActiveModelEntity(ent, false, false, false);
12962         else
12963         {
12964                 switch (vid.renderpath)
12965                 {
12966                 case RENDERPATH_GL20:
12967                 case RENDERPATH_CGGL:
12968                 case RENDERPATH_D3D9:
12969                 case RENDERPATH_D3D10:
12970                 case RENDERPATH_D3D11:
12971                         RSurf_ActiveModelEntity(ent, true, true, false);
12972                         break;
12973                 case RENDERPATH_GL13:
12974                 case RENDERPATH_GL11:
12975                         RSurf_ActiveModelEntity(ent, true, false, false);
12976                         break;
12977                 }
12978         }
12979
12980         if (r_transparentdepthmasking.integer)
12981         {
12982                 qboolean setup = false;
12983                 for (i = 0;i < numsurfaces;i = j)
12984                 {
12985                         j = i + 1;
12986                         surface = rsurface.modelsurfaces + surfacelist[i];
12987                         texture = surface->texture;
12988                         rsurface.texture = R_GetCurrentTexture(texture);
12989                         rsurface.lightmaptexture = NULL;
12990                         rsurface.deluxemaptexture = NULL;
12991                         rsurface.uselightmaptexture = false;
12992                         // scan ahead until we find a different texture
12993                         endsurface = min(i + 1024, numsurfaces);
12994                         texturenumsurfaces = 0;
12995                         texturesurfacelist[texturenumsurfaces++] = surface;
12996                         for (;j < endsurface;j++)
12997                         {
12998                                 surface = rsurface.modelsurfaces + surfacelist[j];
12999                                 if (texture != surface->texture)
13000                                         break;
13001                                 texturesurfacelist[texturenumsurfaces++] = surface;
13002                         }
13003                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13004                                 continue;
13005                         // render the range of surfaces as depth
13006                         if (!setup)
13007                         {
13008                                 setup = true;
13009                                 GL_ColorMask(0,0,0,0);
13010                                 GL_Color(1,1,1,1);
13011                                 GL_DepthTest(true);
13012                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13013                                 GL_DepthMask(true);
13014                                 GL_AlphaTest(false);
13015                                 R_Mesh_ResetTextureState();
13016                                 R_SetupShader_DepthOrShadow();
13017                         }
13018                         RSurf_SetupDepthAndCulling();
13019                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13020                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13021                         RSurf_DrawBatch();
13022                 }
13023                 if (setup)
13024                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13025         }
13026
13027         for (i = 0;i < numsurfaces;i = j)
13028         {
13029                 j = i + 1;
13030                 surface = rsurface.modelsurfaces + surfacelist[i];
13031                 texture = surface->texture;
13032                 rsurface.texture = R_GetCurrentTexture(texture);
13033                 rsurface.lightmaptexture = surface->lightmaptexture;
13034                 rsurface.deluxemaptexture = surface->deluxemaptexture;
13035                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13036                 // scan ahead until we find a different texture
13037                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13038                 texturenumsurfaces = 0;
13039                 texturesurfacelist[texturenumsurfaces++] = surface;
13040                 for (;j < endsurface;j++)
13041                 {
13042                         surface = rsurface.modelsurfaces + surfacelist[j];
13043                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13044                                 break;
13045                         texturesurfacelist[texturenumsurfaces++] = surface;
13046                 }
13047                 // render the range of surfaces
13048                 if (ent == r_refdef.scene.worldentity)
13049                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13050                 else
13051                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13052         }
13053         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13054         GL_AlphaTest(false);
13055 }
13056
13057 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13058 {
13059         // transparent surfaces get pushed off into the transparent queue
13060         int surfacelistindex;
13061         const msurface_t *surface;
13062         vec3_t tempcenter, center;
13063         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13064         {
13065                 surface = texturesurfacelist[surfacelistindex];
13066                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13067                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13068                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13069                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13070                 if (queueentity->transparent_offset) // transparent offset
13071                 {
13072                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13073                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13074                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13075                 }
13076                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13077         }
13078 }
13079
13080 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13081 {
13082         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13083                 return;
13084         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13085                 return;
13086         RSurf_SetupDepthAndCulling();
13087         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13088         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13089         RSurf_DrawBatch();
13090 }
13091
13092 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13093 {
13094         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13095         CHECKGLERROR
13096         if (depthonly)
13097                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13098         else if (prepass)
13099         {
13100                 if (!rsurface.texture->currentnumlayers)
13101                         return;
13102                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13103                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13104                 else
13105                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13106         }
13107         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13108                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13109         else if (!rsurface.texture->currentnumlayers)
13110                 return;
13111         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13112         {
13113                 // in the deferred case, transparent surfaces were queued during prepass
13114                 if (!r_shadow_usingdeferredprepass)
13115                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13116         }
13117         else
13118         {
13119                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13120                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13121         }
13122         CHECKGLERROR
13123 }
13124
13125 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13126 {
13127         int i, j;
13128         texture_t *texture;
13129         // break the surface list down into batches by texture and use of lightmapping
13130         for (i = 0;i < numsurfaces;i = j)
13131         {
13132                 j = i + 1;
13133                 // texture is the base texture pointer, rsurface.texture is the
13134                 // current frame/skin the texture is directing us to use (for example
13135                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13136                 // use skin 1 instead)
13137                 texture = surfacelist[i]->texture;
13138                 rsurface.texture = R_GetCurrentTexture(texture);
13139                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13140                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13141                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13142                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13143                 {
13144                         // if this texture is not the kind we want, skip ahead to the next one
13145                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13146                                 ;
13147                         continue;
13148                 }
13149                 // simply scan ahead until we find a different texture or lightmap state
13150                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13151                         ;
13152                 // render the range of surfaces
13153                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13154         }
13155 }
13156
13157 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13158 {
13159         CHECKGLERROR
13160         if (depthonly)
13161                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13162         else if (prepass)
13163         {
13164                 if (!rsurface.texture->currentnumlayers)
13165                         return;
13166                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13167                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13168                 else
13169                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13170         }
13171         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13172                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13173         else if (!rsurface.texture->currentnumlayers)
13174                 return;
13175         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13176         {
13177                 // in the deferred case, transparent surfaces were queued during prepass
13178                 if (!r_shadow_usingdeferredprepass)
13179                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13180         }
13181         else
13182         {
13183                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13184                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13185         }
13186         CHECKGLERROR
13187 }
13188
13189 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13190 {
13191         int i, j;
13192         texture_t *texture;
13193         // break the surface list down into batches by texture and use of lightmapping
13194         for (i = 0;i < numsurfaces;i = j)
13195         {
13196                 j = i + 1;
13197                 // texture is the base texture pointer, rsurface.texture is the
13198                 // current frame/skin the texture is directing us to use (for example
13199                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13200                 // use skin 1 instead)
13201                 texture = surfacelist[i]->texture;
13202                 rsurface.texture = R_GetCurrentTexture(texture);
13203                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13204                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13205                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13206                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13207                 {
13208                         // if this texture is not the kind we want, skip ahead to the next one
13209                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13210                                 ;
13211                         continue;
13212                 }
13213                 // simply scan ahead until we find a different texture or lightmap state
13214                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13215                         ;
13216                 // render the range of surfaces
13217                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13218         }
13219 }
13220
13221 float locboxvertex3f[6*4*3] =
13222 {
13223         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13224         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13225         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13226         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13227         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13228         1,0,0, 0,0,0, 0,1,0, 1,1,0
13229 };
13230
13231 unsigned short locboxelements[6*2*3] =
13232 {
13233          0, 1, 2, 0, 2, 3,
13234          4, 5, 6, 4, 6, 7,
13235          8, 9,10, 8,10,11,
13236         12,13,14, 12,14,15,
13237         16,17,18, 16,18,19,
13238         20,21,22, 20,22,23
13239 };
13240
13241 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13242 {
13243         int i, j;
13244         cl_locnode_t *loc = (cl_locnode_t *)ent;
13245         vec3_t mins, size;
13246         float vertex3f[6*4*3];
13247         CHECKGLERROR
13248         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13249         GL_DepthMask(false);
13250         GL_DepthRange(0, 1);
13251         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13252         GL_DepthTest(true);
13253         GL_CullFace(GL_NONE);
13254         R_EntityMatrix(&identitymatrix);
13255
13256         R_Mesh_ResetTextureState();
13257
13258         i = surfacelist[0];
13259         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13260                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13261                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13262                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13263
13264         if (VectorCompare(loc->mins, loc->maxs))
13265         {
13266                 VectorSet(size, 2, 2, 2);
13267                 VectorMA(loc->mins, -0.5f, size, mins);
13268         }
13269         else
13270         {
13271                 VectorCopy(loc->mins, mins);
13272                 VectorSubtract(loc->maxs, loc->mins, size);
13273         }
13274
13275         for (i = 0;i < 6*4*3;)
13276                 for (j = 0;j < 3;j++, i++)
13277                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13278
13279         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13280         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13281         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13282 }
13283
13284 void R_DrawLocs(void)
13285 {
13286         int index;
13287         cl_locnode_t *loc, *nearestloc;
13288         vec3_t center;
13289         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13290         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13291         {
13292                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13293                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13294         }
13295 }
13296
13297 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13298 {
13299         if (decalsystem->decals)
13300                 Mem_Free(decalsystem->decals);
13301         memset(decalsystem, 0, sizeof(*decalsystem));
13302 }
13303
13304 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)
13305 {
13306         tridecal_t *decal;
13307         tridecal_t *decals;
13308         int i;
13309
13310         // expand or initialize the system
13311         if (decalsystem->maxdecals <= decalsystem->numdecals)
13312         {
13313                 decalsystem_t old = *decalsystem;
13314                 qboolean useshortelements;
13315                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13316                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13317                 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)));
13318                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13319                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13320                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13321                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13322                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13323                 if (decalsystem->numdecals)
13324                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13325                 if (old.decals)
13326                         Mem_Free(old.decals);
13327                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13328                         decalsystem->element3i[i] = i;
13329                 if (useshortelements)
13330                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13331                                 decalsystem->element3s[i] = i;
13332         }
13333
13334         // grab a decal and search for another free slot for the next one
13335         decals = decalsystem->decals;
13336         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13337         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13338                 ;
13339         decalsystem->freedecal = i;
13340         if (decalsystem->numdecals <= i)
13341                 decalsystem->numdecals = i + 1;
13342
13343         // initialize the decal
13344         decal->lived = 0;
13345         decal->triangleindex = triangleindex;
13346         decal->surfaceindex = surfaceindex;
13347         decal->decalsequence = decalsequence;
13348         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13349         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13350         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13351         decal->color4ub[0][3] = 255;
13352         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13353         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13354         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13355         decal->color4ub[1][3] = 255;
13356         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13357         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13358         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13359         decal->color4ub[2][3] = 255;
13360         decal->vertex3f[0][0] = v0[0];
13361         decal->vertex3f[0][1] = v0[1];
13362         decal->vertex3f[0][2] = v0[2];
13363         decal->vertex3f[1][0] = v1[0];
13364         decal->vertex3f[1][1] = v1[1];
13365         decal->vertex3f[1][2] = v1[2];
13366         decal->vertex3f[2][0] = v2[0];
13367         decal->vertex3f[2][1] = v2[1];
13368         decal->vertex3f[2][2] = v2[2];
13369         decal->texcoord2f[0][0] = t0[0];
13370         decal->texcoord2f[0][1] = t0[1];
13371         decal->texcoord2f[1][0] = t1[0];
13372         decal->texcoord2f[1][1] = t1[1];
13373         decal->texcoord2f[2][0] = t2[0];
13374         decal->texcoord2f[2][1] = t2[1];
13375 }
13376
13377 extern cvar_t cl_decals_bias;
13378 extern cvar_t cl_decals_models;
13379 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13380 // baseparms, parms, temps
13381 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)
13382 {
13383         int cornerindex;
13384         int index;
13385         float v[9][3];
13386         const float *vertex3f;
13387         int numpoints;
13388         float points[2][9][3];
13389         float temp[3];
13390         float tc[9][2];
13391         float f;
13392         float c[9][4];
13393         const int *e;
13394
13395         e = rsurface.modelelement3i + 3*triangleindex;
13396
13397         vertex3f = rsurface.modelvertex3f;
13398
13399         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13400         {
13401                 index = 3*e[cornerindex];
13402                 VectorCopy(vertex3f + index, v[cornerindex]);
13403         }
13404         // cull backfaces
13405         //TriangleNormal(v[0], v[1], v[2], normal);
13406         //if (DotProduct(normal, localnormal) < 0.0f)
13407         //      continue;
13408         // clip by each of the box planes formed from the projection matrix
13409         // if anything survives, we emit the decal
13410         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]);
13411         if (numpoints < 3)
13412                 return;
13413         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]);
13414         if (numpoints < 3)
13415                 return;
13416         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]);
13417         if (numpoints < 3)
13418                 return;
13419         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]);
13420         if (numpoints < 3)
13421                 return;
13422         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]);
13423         if (numpoints < 3)
13424                 return;
13425         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]);
13426         if (numpoints < 3)
13427                 return;
13428         // some part of the triangle survived, so we have to accept it...
13429         if (dynamic)
13430         {
13431                 // dynamic always uses the original triangle
13432                 numpoints = 3;
13433                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13434                 {
13435                         index = 3*e[cornerindex];
13436                         VectorCopy(vertex3f + index, v[cornerindex]);
13437                 }
13438         }
13439         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13440         {
13441                 // convert vertex positions to texcoords
13442                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13443                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13444                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13445                 // calculate distance fade from the projection origin
13446                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13447                 f = bound(0.0f, f, 1.0f);
13448                 c[cornerindex][0] = r * f;
13449                 c[cornerindex][1] = g * f;
13450                 c[cornerindex][2] = b * f;
13451                 c[cornerindex][3] = 1.0f;
13452                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13453         }
13454         if (dynamic)
13455                 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);
13456         else
13457                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13458                         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);
13459 }
13460 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)
13461 {
13462         matrix4x4_t projection;
13463         decalsystem_t *decalsystem;
13464         qboolean dynamic;
13465         dp_model_t *model;
13466         const msurface_t *surface;
13467         const msurface_t *surfaces;
13468         const int *surfacelist;
13469         const texture_t *texture;
13470         int numtriangles;
13471         int numsurfacelist;
13472         int surfacelistindex;
13473         int surfaceindex;
13474         int triangleindex;
13475         float localorigin[3];
13476         float localnormal[3];
13477         float localmins[3];
13478         float localmaxs[3];
13479         float localsize;
13480         //float normal[3];
13481         float planes[6][4];
13482         float angles[3];
13483         bih_t *bih;
13484         int bih_triangles_count;
13485         int bih_triangles[256];
13486         int bih_surfaces[256];
13487
13488         decalsystem = &ent->decalsystem;
13489         model = ent->model;
13490         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13491         {
13492                 R_DecalSystem_Reset(&ent->decalsystem);
13493                 return;
13494         }
13495
13496         if (!model->brush.data_leafs && !cl_decals_models.integer)
13497         {
13498                 if (decalsystem->model)
13499                         R_DecalSystem_Reset(decalsystem);
13500                 return;
13501         }
13502
13503         if (decalsystem->model != model)
13504                 R_DecalSystem_Reset(decalsystem);
13505         decalsystem->model = model;
13506
13507         RSurf_ActiveModelEntity(ent, false, false, false);
13508
13509         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13510         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13511         VectorNormalize(localnormal);
13512         localsize = worldsize*rsurface.inversematrixscale;
13513         localmins[0] = localorigin[0] - localsize;
13514         localmins[1] = localorigin[1] - localsize;
13515         localmins[2] = localorigin[2] - localsize;
13516         localmaxs[0] = localorigin[0] + localsize;
13517         localmaxs[1] = localorigin[1] + localsize;
13518         localmaxs[2] = localorigin[2] + localsize;
13519
13520         //VectorCopy(localnormal, planes[4]);
13521         //VectorVectors(planes[4], planes[2], planes[0]);
13522         AnglesFromVectors(angles, localnormal, NULL, false);
13523         AngleVectors(angles, planes[0], planes[2], planes[4]);
13524         VectorNegate(planes[0], planes[1]);
13525         VectorNegate(planes[2], planes[3]);
13526         VectorNegate(planes[4], planes[5]);
13527         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13528         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13529         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13530         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13531         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13532         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13533
13534 #if 1
13535 // works
13536 {
13537         matrix4x4_t forwardprojection;
13538         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13539         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13540 }
13541 #else
13542 // broken
13543 {
13544         float projectionvector[4][3];
13545         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13546         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13547         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13548         projectionvector[0][0] = planes[0][0] * ilocalsize;
13549         projectionvector[0][1] = planes[1][0] * ilocalsize;
13550         projectionvector[0][2] = planes[2][0] * ilocalsize;
13551         projectionvector[1][0] = planes[0][1] * ilocalsize;
13552         projectionvector[1][1] = planes[1][1] * ilocalsize;
13553         projectionvector[1][2] = planes[2][1] * ilocalsize;
13554         projectionvector[2][0] = planes[0][2] * ilocalsize;
13555         projectionvector[2][1] = planes[1][2] * ilocalsize;
13556         projectionvector[2][2] = planes[2][2] * ilocalsize;
13557         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13558         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13559         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13560         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13561 }
13562 #endif
13563
13564         dynamic = model->surfmesh.isanimated;
13565         numsurfacelist = model->nummodelsurfaces;
13566         surfacelist = model->sortedmodelsurfaces;
13567         surfaces = model->data_surfaces;
13568
13569         bih = NULL;
13570         bih_triangles_count = -1;
13571         if(!dynamic)
13572         {
13573                 if(model->render_bih.numleafs)
13574                         bih = &model->render_bih;
13575                 else if(model->collision_bih.numleafs)
13576                         bih = &model->collision_bih;
13577         }
13578         if(bih)
13579                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13580         if(bih_triangles_count == 0)
13581                 return;
13582         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13583                 return;
13584         if(bih_triangles_count > 0)
13585         {
13586                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13587                 {
13588                         surfaceindex = bih_surfaces[triangleindex];
13589                         surface = surfaces + surfaceindex;
13590                         texture = surface->texture;
13591                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13592                                 continue;
13593                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13594                                 continue;
13595                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13596                 }
13597         }
13598         else
13599         {
13600                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13601                 {
13602                         surfaceindex = surfacelist[surfacelistindex];
13603                         surface = surfaces + surfaceindex;
13604                         // check cull box first because it rejects more than any other check
13605                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13606                                 continue;
13607                         // skip transparent surfaces
13608                         texture = surface->texture;
13609                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13610                                 continue;
13611                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13612                                 continue;
13613                         numtriangles = surface->num_triangles;
13614                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13615                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13616                 }
13617         }
13618 }
13619
13620 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13621 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)
13622 {
13623         int renderentityindex;
13624         float worldmins[3];
13625         float worldmaxs[3];
13626         entity_render_t *ent;
13627
13628         if (!cl_decals_newsystem.integer)
13629                 return;
13630
13631         worldmins[0] = worldorigin[0] - worldsize;
13632         worldmins[1] = worldorigin[1] - worldsize;
13633         worldmins[2] = worldorigin[2] - worldsize;
13634         worldmaxs[0] = worldorigin[0] + worldsize;
13635         worldmaxs[1] = worldorigin[1] + worldsize;
13636         worldmaxs[2] = worldorigin[2] + worldsize;
13637
13638         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13639
13640         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13641         {
13642                 ent = r_refdef.scene.entities[renderentityindex];
13643                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13644                         continue;
13645
13646                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13647         }
13648 }
13649
13650 typedef struct r_decalsystem_splatqueue_s
13651 {
13652         vec3_t worldorigin;
13653         vec3_t worldnormal;
13654         float color[4];
13655         float tcrange[4];
13656         float worldsize;
13657         int decalsequence;
13658 }
13659 r_decalsystem_splatqueue_t;
13660
13661 int r_decalsystem_numqueued = 0;
13662 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13663
13664 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)
13665 {
13666         r_decalsystem_splatqueue_t *queue;
13667
13668         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13669                 return;
13670
13671         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13672         VectorCopy(worldorigin, queue->worldorigin);
13673         VectorCopy(worldnormal, queue->worldnormal);
13674         Vector4Set(queue->color, r, g, b, a);
13675         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13676         queue->worldsize = worldsize;
13677         queue->decalsequence = cl.decalsequence++;
13678 }
13679
13680 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13681 {
13682         int i;
13683         r_decalsystem_splatqueue_t *queue;
13684
13685         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13686                 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);
13687         r_decalsystem_numqueued = 0;
13688 }
13689
13690 extern cvar_t cl_decals_max;
13691 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13692 {
13693         int i;
13694         decalsystem_t *decalsystem = &ent->decalsystem;
13695         int numdecals;
13696         int killsequence;
13697         tridecal_t *decal;
13698         float frametime;
13699         float lifetime;
13700
13701         if (!decalsystem->numdecals)
13702                 return;
13703
13704         if (r_showsurfaces.integer)
13705                 return;
13706
13707         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13708         {
13709                 R_DecalSystem_Reset(decalsystem);
13710                 return;
13711         }
13712
13713         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13714         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13715
13716         if (decalsystem->lastupdatetime)
13717                 frametime = (cl.time - decalsystem->lastupdatetime);
13718         else
13719                 frametime = 0;
13720         decalsystem->lastupdatetime = cl.time;
13721         decal = decalsystem->decals;
13722         numdecals = decalsystem->numdecals;
13723
13724         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13725         {
13726                 if (decal->color4ub[0][3])
13727                 {
13728                         decal->lived += frametime;
13729                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13730                         {
13731                                 memset(decal, 0, sizeof(*decal));
13732                                 if (decalsystem->freedecal > i)
13733                                         decalsystem->freedecal = i;
13734                         }
13735                 }
13736         }
13737         decal = decalsystem->decals;
13738         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13739                 numdecals--;
13740
13741         // collapse the array by shuffling the tail decals into the gaps
13742         for (;;)
13743         {
13744                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13745                         decalsystem->freedecal++;
13746                 if (decalsystem->freedecal == numdecals)
13747                         break;
13748                 decal[decalsystem->freedecal] = decal[--numdecals];
13749         }
13750
13751         decalsystem->numdecals = numdecals;
13752
13753         if (numdecals <= 0)
13754         {
13755                 // if there are no decals left, reset decalsystem
13756                 R_DecalSystem_Reset(decalsystem);
13757         }
13758 }
13759
13760 extern skinframe_t *decalskinframe;
13761 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13762 {
13763         int i;
13764         decalsystem_t *decalsystem = &ent->decalsystem;
13765         int numdecals;
13766         tridecal_t *decal;
13767         float faderate;
13768         float alpha;
13769         float *v3f;
13770         float *c4f;
13771         float *t2f;
13772         const int *e;
13773         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13774         int numtris = 0;
13775
13776         numdecals = decalsystem->numdecals;
13777         if (!numdecals)
13778                 return;
13779
13780         if (r_showsurfaces.integer)
13781                 return;
13782
13783         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13784         {
13785                 R_DecalSystem_Reset(decalsystem);
13786                 return;
13787         }
13788
13789         // if the model is static it doesn't matter what value we give for
13790         // wantnormals and wanttangents, so this logic uses only rules applicable
13791         // to a model, knowing that they are meaningless otherwise
13792         if (ent == r_refdef.scene.worldentity)
13793                 RSurf_ActiveWorldEntity();
13794         else
13795                 RSurf_ActiveModelEntity(ent, false, false, false);
13796
13797         decalsystem->lastupdatetime = cl.time;
13798         decal = decalsystem->decals;
13799
13800         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13801
13802         // update vertex positions for animated models
13803         v3f = decalsystem->vertex3f;
13804         c4f = decalsystem->color4f;
13805         t2f = decalsystem->texcoord2f;
13806         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13807         {
13808                 if (!decal->color4ub[0][3])
13809                         continue;
13810
13811                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13812                         continue;
13813
13814                 // update color values for fading decals
13815                 if (decal->lived >= cl_decals_time.value)
13816                 {
13817                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13818                         alpha *= (1.0f/255.0f);
13819                 }
13820                 else
13821                         alpha = 1.0f/255.0f;
13822
13823                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13824                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13825                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13826                 c4f[ 3] = 1;
13827                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13828                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13829                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13830                 c4f[ 7] = 1;
13831                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13832                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13833                 c4f[10] = decal->color4ub[2][2] * alpha;
13834                 c4f[11] = 1;
13835
13836                 t2f[0] = decal->texcoord2f[0][0];
13837                 t2f[1] = decal->texcoord2f[0][1];
13838                 t2f[2] = decal->texcoord2f[1][0];
13839                 t2f[3] = decal->texcoord2f[1][1];
13840                 t2f[4] = decal->texcoord2f[2][0];
13841                 t2f[5] = decal->texcoord2f[2][1];
13842
13843                 // update vertex positions for animated models
13844                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13845                 {
13846                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13847                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13848                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13849                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13850                 }
13851                 else
13852                 {
13853                         VectorCopy(decal->vertex3f[0], v3f);
13854                         VectorCopy(decal->vertex3f[1], v3f + 3);
13855                         VectorCopy(decal->vertex3f[2], v3f + 6);
13856                 }
13857
13858                 if (r_refdef.fogenabled)
13859                 {
13860                         alpha = RSurf_FogVertex(v3f);
13861                         VectorScale(c4f, alpha, c4f);
13862                         alpha = RSurf_FogVertex(v3f + 3);
13863                         VectorScale(c4f + 4, alpha, c4f + 4);
13864                         alpha = RSurf_FogVertex(v3f + 6);
13865                         VectorScale(c4f + 8, alpha, c4f + 8);
13866                 }
13867
13868                 v3f += 9;
13869                 c4f += 12;
13870                 t2f += 6;
13871                 numtris++;
13872         }
13873
13874         if (numtris > 0)
13875         {
13876                 r_refdef.stats.drawndecals += numtris;
13877
13878                 // now render the decals all at once
13879                 // (this assumes they all use one particle font texture!)
13880                 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);
13881                 R_Mesh_ResetTextureState();
13882                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13883                 GL_DepthMask(false);
13884                 GL_DepthRange(0, 1);
13885                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13886                 GL_DepthTest(true);
13887                 GL_CullFace(GL_NONE);
13888                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13889                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13890                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13891         }
13892 }
13893
13894 static void R_DrawModelDecals(void)
13895 {
13896         int i, numdecals;
13897
13898         // fade faster when there are too many decals
13899         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13900         for (i = 0;i < r_refdef.scene.numentities;i++)
13901                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13902
13903         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13904         for (i = 0;i < r_refdef.scene.numentities;i++)
13905                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13906                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13907
13908         R_DecalSystem_ApplySplatEntitiesQueue();
13909
13910         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13911         for (i = 0;i < r_refdef.scene.numentities;i++)
13912                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13913
13914         r_refdef.stats.totaldecals += numdecals;
13915
13916         if (r_showsurfaces.integer)
13917                 return;
13918
13919         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13920
13921         for (i = 0;i < r_refdef.scene.numentities;i++)
13922         {
13923                 if (!r_refdef.viewcache.entityvisible[i])
13924                         continue;
13925                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13926                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13927         }
13928 }
13929
13930 extern cvar_t mod_collision_bih;
13931 void R_DrawDebugModel(void)
13932 {
13933         entity_render_t *ent = rsurface.entity;
13934         int i, j, k, l, flagsmask;
13935         const msurface_t *surface;
13936         dp_model_t *model = ent->model;
13937         vec3_t v;
13938
13939         switch(vid.renderpath)
13940         {
13941         case RENDERPATH_GL11:
13942         case RENDERPATH_GL13:
13943         case RENDERPATH_GL20:
13944         case RENDERPATH_CGGL:
13945                 break;
13946         case RENDERPATH_D3D9:
13947                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13948                 return;
13949         case RENDERPATH_D3D10:
13950                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13951                 return;
13952         case RENDERPATH_D3D11:
13953                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13954                 return;
13955         }
13956
13957         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13958
13959         R_Mesh_ResetTextureState();
13960         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13961         GL_DepthRange(0, 1);
13962         GL_DepthTest(!r_showdisabledepthtest.integer);
13963         GL_DepthMask(false);
13964         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13965
13966         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13967         {
13968                 int triangleindex;
13969                 int bihleafindex;
13970                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13971                 const q3mbrush_t *brush;
13972                 const bih_t *bih = &model->collision_bih;
13973                 const bih_leaf_t *bihleaf;
13974                 float vertex3f[3][3];
13975                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13976                 cullbox = false;
13977                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13978                 {
13979                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13980                                 continue;
13981                         switch (bihleaf->type)
13982                         {
13983                         case BIH_BRUSH:
13984                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13985                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13986                                 {
13987                                         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);
13988                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13989                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13990                                 }
13991                                 break;
13992                         case BIH_COLLISIONTRIANGLE:
13993                                 triangleindex = bihleaf->itemindex;
13994                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13995                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13996                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13997                                 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);
13998                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13999                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14000                                 break;
14001                         case BIH_RENDERTRIANGLE:
14002                                 triangleindex = bihleaf->itemindex;
14003                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14004                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14005                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14006                                 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);
14007                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14008                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14009                                 break;
14010                         }
14011                 }
14012         }
14013
14014         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14015
14016         if (r_showtris.integer || r_shownormals.integer)
14017         {
14018                 if (r_showdisabledepthtest.integer)
14019                 {
14020                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14021                         GL_DepthMask(false);
14022                 }
14023                 else
14024                 {
14025                         GL_BlendFunc(GL_ONE, GL_ZERO);
14026                         GL_DepthMask(true);
14027                 }
14028                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14029                 {
14030                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14031                                 continue;
14032                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14033                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14034                         {
14035                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14036                                 if (r_showtris.value > 0)
14037                                 {
14038                                         if (!rsurface.texture->currentlayers->depthmask)
14039                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14040                                         else if (ent == r_refdef.scene.worldentity)
14041                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14042                                         else
14043                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14044                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14045                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14046                                         RSurf_DrawBatch();
14047                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14048                                         CHECKGLERROR
14049                                 }
14050                                 if (r_shownormals.value < 0)
14051                                 {
14052                                         qglBegin(GL_LINES);
14053                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14054                                         {
14055                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14056                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14057                                                 qglVertex3f(v[0], v[1], v[2]);
14058                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14059                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14060                                                 qglVertex3f(v[0], v[1], v[2]);
14061                                         }
14062                                         qglEnd();
14063                                         CHECKGLERROR
14064                                 }
14065                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14066                                 {
14067                                         qglBegin(GL_LINES);
14068                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14069                                         {
14070                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14071                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14072                                                 qglVertex3f(v[0], v[1], v[2]);
14073                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14074                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14075                                                 qglVertex3f(v[0], v[1], v[2]);
14076                                         }
14077                                         qglEnd();
14078                                         CHECKGLERROR
14079                                         qglBegin(GL_LINES);
14080                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14081                                         {
14082                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14083                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14084                                                 qglVertex3f(v[0], v[1], v[2]);
14085                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14086                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14087                                                 qglVertex3f(v[0], v[1], v[2]);
14088                                         }
14089                                         qglEnd();
14090                                         CHECKGLERROR
14091                                         qglBegin(GL_LINES);
14092                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14093                                         {
14094                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14095                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14096                                                 qglVertex3f(v[0], v[1], v[2]);
14097                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14098                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14099                                                 qglVertex3f(v[0], v[1], v[2]);
14100                                         }
14101                                         qglEnd();
14102                                         CHECKGLERROR
14103                                 }
14104                         }
14105                 }
14106                 rsurface.texture = NULL;
14107         }
14108 }
14109
14110 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14111 int r_maxsurfacelist = 0;
14112 const msurface_t **r_surfacelist = NULL;
14113 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14114 {
14115         int i, j, endj, flagsmask;
14116         dp_model_t *model = r_refdef.scene.worldmodel;
14117         msurface_t *surfaces;
14118         unsigned char *update;
14119         int numsurfacelist = 0;
14120         if (model == NULL)
14121                 return;
14122
14123         if (r_maxsurfacelist < model->num_surfaces)
14124         {
14125                 r_maxsurfacelist = model->num_surfaces;
14126                 if (r_surfacelist)
14127                         Mem_Free((msurface_t**)r_surfacelist);
14128                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14129         }
14130
14131         RSurf_ActiveWorldEntity();
14132
14133         surfaces = model->data_surfaces;
14134         update = model->brushq1.lightmapupdateflags;
14135
14136         // update light styles on this submodel
14137         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14138         {
14139                 model_brush_lightstyleinfo_t *style;
14140                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14141                 {
14142                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14143                         {
14144                                 int *list = style->surfacelist;
14145                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14146                                 for (j = 0;j < style->numsurfaces;j++)
14147                                         update[list[j]] = true;
14148                         }
14149                 }
14150         }
14151
14152         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14153
14154         if (debug)
14155         {
14156                 R_DrawDebugModel();
14157                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14158                 return;
14159         }
14160
14161         rsurface.lightmaptexture = NULL;
14162         rsurface.deluxemaptexture = NULL;
14163         rsurface.uselightmaptexture = false;
14164         rsurface.texture = NULL;
14165         rsurface.rtlight = NULL;
14166         numsurfacelist = 0;
14167         // add visible surfaces to draw list
14168         for (i = 0;i < model->nummodelsurfaces;i++)
14169         {
14170                 j = model->sortedmodelsurfaces[i];
14171                 if (r_refdef.viewcache.world_surfacevisible[j])
14172                         r_surfacelist[numsurfacelist++] = surfaces + j;
14173         }
14174         // update lightmaps if needed
14175         if (model->brushq1.firstrender)
14176         {
14177                 model->brushq1.firstrender = false;
14178                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14179                         if (update[j])
14180                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14181         }
14182         else if (update)
14183         {
14184                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14185                         if (r_refdef.viewcache.world_surfacevisible[j])
14186                                 if (update[j])
14187                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14188         }
14189         // don't do anything if there were no surfaces
14190         if (!numsurfacelist)
14191         {
14192                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14193                 return;
14194         }
14195         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14196         GL_AlphaTest(false);
14197
14198         // add to stats if desired
14199         if (r_speeds.integer && !skysurfaces && !depthonly)
14200         {
14201                 r_refdef.stats.world_surfaces += numsurfacelist;
14202                 for (j = 0;j < numsurfacelist;j++)
14203                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14204         }
14205
14206         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14207 }
14208
14209 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14210 {
14211         int i, j, endj, flagsmask;
14212         dp_model_t *model = ent->model;
14213         msurface_t *surfaces;
14214         unsigned char *update;
14215         int numsurfacelist = 0;
14216         if (model == NULL)
14217                 return;
14218
14219         if (r_maxsurfacelist < model->num_surfaces)
14220         {
14221                 r_maxsurfacelist = model->num_surfaces;
14222                 if (r_surfacelist)
14223                         Mem_Free((msurface_t **)r_surfacelist);
14224                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14225         }
14226
14227         // if the model is static it doesn't matter what value we give for
14228         // wantnormals and wanttangents, so this logic uses only rules applicable
14229         // to a model, knowing that they are meaningless otherwise
14230         if (ent == r_refdef.scene.worldentity)
14231                 RSurf_ActiveWorldEntity();
14232         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14233                 RSurf_ActiveModelEntity(ent, false, false, false);
14234         else if (prepass)
14235                 RSurf_ActiveModelEntity(ent, true, true, true);
14236         else if (depthonly)
14237         {
14238                 switch (vid.renderpath)
14239                 {
14240                 case RENDERPATH_GL20:
14241                 case RENDERPATH_CGGL:
14242                 case RENDERPATH_D3D9:
14243                 case RENDERPATH_D3D10:
14244                 case RENDERPATH_D3D11:
14245                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14246                         break;
14247                 case RENDERPATH_GL13:
14248                 case RENDERPATH_GL11:
14249                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14250                         break;
14251                 }
14252         }
14253         else
14254         {
14255                 switch (vid.renderpath)
14256                 {
14257                 case RENDERPATH_GL20:
14258                 case RENDERPATH_CGGL:
14259                 case RENDERPATH_D3D9:
14260                 case RENDERPATH_D3D10:
14261                 case RENDERPATH_D3D11:
14262                         RSurf_ActiveModelEntity(ent, true, true, false);
14263                         break;
14264                 case RENDERPATH_GL13:
14265                 case RENDERPATH_GL11:
14266                         RSurf_ActiveModelEntity(ent, true, false, false);
14267                         break;
14268                 }
14269         }
14270
14271         surfaces = model->data_surfaces;
14272         update = model->brushq1.lightmapupdateflags;
14273
14274         // update light styles
14275         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14276         {
14277                 model_brush_lightstyleinfo_t *style;
14278                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14279                 {
14280                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14281                         {
14282                                 int *list = style->surfacelist;
14283                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14284                                 for (j = 0;j < style->numsurfaces;j++)
14285                                         update[list[j]] = true;
14286                         }
14287                 }
14288         }
14289
14290         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14291
14292         if (debug)
14293         {
14294                 R_DrawDebugModel();
14295                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14296                 return;
14297         }
14298
14299         rsurface.lightmaptexture = NULL;
14300         rsurface.deluxemaptexture = NULL;
14301         rsurface.uselightmaptexture = false;
14302         rsurface.texture = NULL;
14303         rsurface.rtlight = NULL;
14304         numsurfacelist = 0;
14305         // add visible surfaces to draw list
14306         for (i = 0;i < model->nummodelsurfaces;i++)
14307                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14308         // don't do anything if there were no surfaces
14309         if (!numsurfacelist)
14310         {
14311                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14312                 return;
14313         }
14314         // update lightmaps if needed
14315         if (update)
14316         {
14317                 int updated = 0;
14318                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14319                 {
14320                         if (update[j])
14321                         {
14322                                 updated++;
14323                                 R_BuildLightMap(ent, surfaces + j);
14324                         }
14325                 }
14326         }
14327         if (update)
14328                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14329                         if (update[j])
14330                                 R_BuildLightMap(ent, surfaces + j);
14331         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14332         GL_AlphaTest(false);
14333
14334         // add to stats if desired
14335         if (r_speeds.integer && !skysurfaces && !depthonly)
14336         {
14337                 r_refdef.stats.entities_surfaces += numsurfacelist;
14338                 for (j = 0;j < numsurfacelist;j++)
14339                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14340         }
14341
14342         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14343 }
14344
14345 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14346 {
14347         static texture_t texture;
14348         static msurface_t surface;
14349         const msurface_t *surfacelist = &surface;
14350
14351         // fake enough texture and surface state to render this geometry
14352
14353         texture.update_lastrenderframe = -1; // regenerate this texture
14354         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14355         texture.currentskinframe = skinframe;
14356         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14357         texture.offsetmapping = OFFSETMAPPING_OFF;
14358         texture.offsetscale = 1;
14359         texture.specularscalemod = 1;
14360         texture.specularpowermod = 1;
14361
14362         surface.texture = &texture;
14363         surface.num_triangles = numtriangles;
14364         surface.num_firsttriangle = firsttriangle;
14365         surface.num_vertices = numvertices;
14366         surface.num_firstvertex = firstvertex;
14367
14368         // now render it
14369         rsurface.texture = R_GetCurrentTexture(surface.texture);
14370         rsurface.lightmaptexture = NULL;
14371         rsurface.deluxemaptexture = NULL;
14372         rsurface.uselightmaptexture = false;
14373         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14374 }
14375
14376 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)
14377 {
14378         static msurface_t surface;
14379         const msurface_t *surfacelist = &surface;
14380
14381         // fake enough texture and surface state to render this geometry
14382
14383         surface.texture = texture;
14384         surface.num_triangles = numtriangles;
14385         surface.num_firsttriangle = firsttriangle;
14386         surface.num_vertices = numvertices;
14387         surface.num_firstvertex = firstvertex;
14388
14389         // now render it
14390         rsurface.texture = R_GetCurrentTexture(surface.texture);
14391         rsurface.lightmaptexture = NULL;
14392         rsurface.deluxemaptexture = NULL;
14393         rsurface.uselightmaptexture = false;
14394         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14395 }