implemented Direct3D9 renderer (off by default), not very optimized but almost comple...
[divverent/darkplaces.git] / r_shadow.c
1
2 /*
3 Terminology: Stencil Shadow Volume (sometimes called Stencil Shadows)
4 An extrusion of the lit faces, beginning at the original geometry and ending
5 further from the light source than the original geometry (presumably at least
6 as far as the light's radius, if the light has a radius at all), capped at
7 both front and back to avoid any problems (extrusion from dark faces also
8 works but has a different set of problems)
9
10 This is normally rendered using Carmack's Reverse technique, in which
11 backfaces behind zbuffer (zfail) increment the stencil, and frontfaces behind
12 zbuffer (zfail) decrement the stencil, the result is a stencil value of zero
13 where shadows did not intersect the visible geometry, suitable as a stencil
14 mask for rendering lighting everywhere but shadow.
15
16 In our case to hopefully avoid the Creative Labs patent, we draw the backfaces
17 as decrement and the frontfaces as increment, and we redefine the DepthFunc to
18 GL_LESS (the patent uses GL_GEQUAL) which causes zfail when behind surfaces
19 and zpass when infront (the patent draws where zpass with a GL_GEQUAL test),
20 additionally we clear stencil to 128 to avoid the need for the unclamped
21 incr/decr extension (not related to patent).
22
23 Patent warning:
24 This algorithm may be covered by Creative's patent (US Patent #6384822),
25 however that patent is quite specific about increment on backfaces and
26 decrement on frontfaces where zpass with GL_GEQUAL depth test, which is
27 opposite this implementation and partially opposite Carmack's Reverse paper
28 (which uses GL_LESS, but increments on backfaces and decrements on frontfaces).
29
30
31
32 Terminology: Stencil Light Volume (sometimes called Light Volumes)
33 Similar to a Stencil Shadow Volume, but inverted; rather than containing the
34 areas in shadow it contains the areas in light, this can only be built
35 quickly for certain limited cases (such as portal visibility from a point),
36 but is quite useful for some effects (sunlight coming from sky polygons is
37 one possible example, translucent occluders is another example).
38
39
40
41 Terminology: Optimized Stencil Shadow Volume
42 A Stencil Shadow Volume that has been processed sufficiently to ensure it has
43 no duplicate coverage of areas (no need to shadow an area twice), often this
44 greatly improves performance but is an operation too costly to use on moving
45 lights (however completely optimal Stencil Light Volumes can be constructed
46 in some ideal cases).
47
48
49
50 Terminology: Per Pixel Lighting (sometimes abbreviated PPL)
51 Per pixel evaluation of lighting equations, at a bare minimum this involves
52 DOT3 shading of diffuse lighting (per pixel dotproduct of negated incidence
53 vector and surface normal, using a texture of the surface bumps, called a
54 NormalMap) if supported by hardware; in our case there is support for cards
55 which are incapable of DOT3, the quality is quite poor however.  Additionally
56 it is desirable to have specular evaluation per pixel, per vertex
57 normalization of specular halfangle vectors causes noticable distortion but
58 is unavoidable on hardware without GL_ARB_fragment_program or
59 GL_ARB_fragment_shader.
60
61
62
63 Terminology: Normalization CubeMap
64 A cubemap containing normalized dot3-encoded (vectors of length 1 or less
65 encoded as RGB colors) for any possible direction, this technique allows per
66 pixel calculation of incidence vector for per pixel lighting purposes, which
67 would not otherwise be possible per pixel without GL_ARB_fragment_program or
68 GL_ARB_fragment_shader.
69
70
71
72 Terminology: 2D+1D Attenuation Texturing
73 A very crude approximation of light attenuation with distance which results
74 in cylindrical light shapes which fade vertically as a streak (some games
75 such as Doom3 allow this to be rotated to be less noticable in specific
76 cases), the technique is simply modulating lighting by two 2D textures (which
77 can be the same) on different axes of projection (XY and Z, typically), this
78 is the second best technique available without 3D Attenuation Texturing,
79 GL_ARB_fragment_program or GL_ARB_fragment_shader technology.
80
81
82
83 Terminology: 2D+1D Inverse Attenuation Texturing
84 A clever method described in papers on the Abducted engine, this has a squared
85 distance texture (bright on the outside, black in the middle), which is used
86 twice using GL_ADD blending, the result of this is used in an inverse modulate
87 (GL_ONE_MINUS_DST_ALPHA, GL_ZERO) to implement the equation
88 lighting*=(1-((X*X+Y*Y)+(Z*Z))) which is spherical (unlike 2D+1D attenuation
89 texturing).
90
91
92
93 Terminology: 3D Attenuation Texturing
94 A slightly crude approximation of light attenuation with distance, its flaws
95 are limited radius and resolution (performance tradeoffs).
96
97
98
99 Terminology: 3D Attenuation-Normalization Texturing
100 A 3D Attenuation Texture merged with a Normalization CubeMap, by making the
101 vectors shorter the lighting becomes darker, a very effective optimization of
102 diffuse lighting if 3D Attenuation Textures are already used.
103
104
105
106 Terminology: Light Cubemap Filtering
107 A technique for modeling non-uniform light distribution according to
108 direction, for example a lantern may use a cubemap to describe the light
109 emission pattern of the cage around the lantern (as well as soot buildup
110 discoloring the light in certain areas), often also used for softened grate
111 shadows and light shining through a stained glass window (done crudely by
112 texturing the lighting with a cubemap), another good example would be a disco
113 light.  This technique is used heavily in many games (Doom3 does not support
114 this however).
115
116
117
118 Terminology: Light Projection Filtering
119 A technique for modeling shadowing of light passing through translucent
120 surfaces, allowing stained glass windows and other effects to be done more
121 elegantly than possible with Light Cubemap Filtering by applying an occluder
122 texture to the lighting combined with a stencil light volume to limit the lit
123 area, this technique is used by Doom3 for spotlights and flashlights, among
124 other things, this can also be used more generally to render light passing
125 through multiple translucent occluders in a scene (using a light volume to
126 describe the area beyond the occluder, and thus mask off rendering of all
127 other areas).
128
129
130
131 Terminology: Doom3 Lighting
132 A combination of Stencil Shadow Volume, Per Pixel Lighting, Normalization
133 CubeMap, 2D+1D Attenuation Texturing, and Light Projection Filtering, as
134 demonstrated by the game Doom3.
135 */
136
137 #include "quakedef.h"
138 #include "r_shadow.h"
139 #include "cl_collision.h"
140 #include "portals.h"
141 #include "image.h"
142
143 #ifdef SUPPORTD3D
144 #include <d3d9.h>
145 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
146 #endif
147
148 extern void R_Shadow_EditLights_Init(void);
149
150 typedef enum r_shadow_rendermode_e
151 {
152         R_SHADOW_RENDERMODE_NONE,
153         R_SHADOW_RENDERMODE_ZPASS_STENCIL,
154         R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL,
155         R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE,
156         R_SHADOW_RENDERMODE_ZFAIL_STENCIL,
157         R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL,
158         R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE,
159         R_SHADOW_RENDERMODE_LIGHT_VERTEX,
160         R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN,
161         R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN,
162         R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN,
163         R_SHADOW_RENDERMODE_LIGHT_GLSL,
164         R_SHADOW_RENDERMODE_VISIBLEVOLUMES,
165         R_SHADOW_RENDERMODE_VISIBLELIGHTING,
166         R_SHADOW_RENDERMODE_SHADOWMAP2D,
167         R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE,
168         R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE,
169 }
170 r_shadow_rendermode_t;
171
172 typedef enum r_shadow_shadowmode_e
173 {
174     R_SHADOW_SHADOWMODE_STENCIL,
175     R_SHADOW_SHADOWMODE_SHADOWMAP2D,
176     R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE,
177     R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE
178 }
179 r_shadow_shadowmode_t;
180
181 r_shadow_rendermode_t r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
182 r_shadow_rendermode_t r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_NONE;
183 r_shadow_rendermode_t r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_NONE;
184 r_shadow_rendermode_t r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_NONE;
185 qboolean r_shadow_usingshadowmaprect;
186 qboolean r_shadow_usingshadowmap2d;
187 qboolean r_shadow_usingshadowmapcube;
188 qboolean r_shadow_usingshadowmaportho;
189 int r_shadow_shadowmapside;
190 float r_shadow_shadowmap_texturescale[2];
191 float r_shadow_shadowmap_parameters[4];
192 #if 0
193 int r_shadow_drawbuffer;
194 int r_shadow_readbuffer;
195 #endif
196 int r_shadow_cullface_front, r_shadow_cullface_back;
197 GLuint r_shadow_fborectangle;
198 GLuint r_shadow_fbocubeside[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
199 GLuint r_shadow_fbo2d;
200 r_shadow_shadowmode_t r_shadow_shadowmode;
201 int r_shadow_shadowmapfilterquality;
202 int r_shadow_shadowmaptexturetype;
203 int r_shadow_shadowmapdepthbits;
204 int r_shadow_shadowmapmaxsize;
205 qboolean r_shadow_shadowmapvsdct;
206 qboolean r_shadow_shadowmapsampler;
207 int r_shadow_shadowmappcf;
208 int r_shadow_shadowmapborder;
209 matrix4x4_t r_shadow_shadowmapmatrix;
210 int r_shadow_lightscissor[4];
211 qboolean r_shadow_usingdeferredprepass;
212
213 int maxshadowtriangles;
214 int *shadowelements;
215
216 int maxshadowvertices;
217 float *shadowvertex3f;
218
219 int maxshadowmark;
220 int numshadowmark;
221 int *shadowmark;
222 int *shadowmarklist;
223 int shadowmarkcount;
224
225 int maxshadowsides;
226 int numshadowsides;
227 unsigned char *shadowsides;
228 int *shadowsideslist;
229
230 int maxvertexupdate;
231 int *vertexupdate;
232 int *vertexremap;
233 int vertexupdatenum;
234
235 int r_shadow_buffer_numleafpvsbytes;
236 unsigned char *r_shadow_buffer_visitingleafpvs;
237 unsigned char *r_shadow_buffer_leafpvs;
238 int *r_shadow_buffer_leaflist;
239
240 int r_shadow_buffer_numsurfacepvsbytes;
241 unsigned char *r_shadow_buffer_surfacepvs;
242 int *r_shadow_buffer_surfacelist;
243 unsigned char *r_shadow_buffer_surfacesides;
244
245 int r_shadow_buffer_numshadowtrispvsbytes;
246 unsigned char *r_shadow_buffer_shadowtrispvs;
247 int r_shadow_buffer_numlighttrispvsbytes;
248 unsigned char *r_shadow_buffer_lighttrispvs;
249
250 rtexturepool_t *r_shadow_texturepool;
251 rtexture_t *r_shadow_attenuationgradienttexture;
252 rtexture_t *r_shadow_attenuation2dtexture;
253 rtexture_t *r_shadow_attenuation3dtexture;
254 skinframe_t *r_shadow_lightcorona;
255 rtexture_t *r_shadow_shadowmaprectangletexture;
256 rtexture_t *r_shadow_shadowmap2dtexture;
257 rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
258 rtexture_t *r_shadow_shadowmap2dcolortexture;
259 rtexture_t *r_shadow_shadowmapvsdcttexture;
260 int r_shadow_shadowmapsize; // changes for each light based on distance
261 int r_shadow_shadowmaplod; // changes for each light based on distance
262
263 GLuint r_shadow_prepassgeometryfbo;
264 GLuint r_shadow_prepasslightingfbo;
265 int r_shadow_prepass_width;
266 int r_shadow_prepass_height;
267 rtexture_t *r_shadow_prepassgeometrydepthtexture;
268 rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
269 rtexture_t *r_shadow_prepasslightingdiffusetexture;
270 rtexture_t *r_shadow_prepasslightingspeculartexture;
271
272 // lights are reloaded when this changes
273 char r_shadow_mapname[MAX_QPATH];
274
275 // used only for light filters (cubemaps)
276 rtexturepool_t *r_shadow_filters_texturepool;
277
278 static const GLenum r_shadow_prepasslightingdrawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
279
280 cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "0", "generate fake bumpmaps from diffuse textures at this bumpyness, try 4 to match tenebrae, higher values increase depth, requires r_restart to take effect"};
281 cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4", "what magnitude to interpret _bump.tga textures as, higher values increase depth, requires r_restart to take effect"};
282 cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1", "renders only one light, for level design purposes or debugging"};
283 cvar_t r_shadow_deferred = {CVAR_SAVE, "r_shadow_deferred", "0", "uses image-based lighting instead of geometry-based lighting, the method used renders a depth image and a normalmap image, renders lights into separate diffuse and specular images, and then combines this into the normal rendering, requires r_shadow_shadowmapping"};
284 cvar_t r_shadow_deferred_8bitrange = {CVAR_SAVE, "r_shadow_deferred_8bitrange", "2", "dynamic range of image-based lighting when using 32bit color (does not apply to fp)"};
285 //cvar_t r_shadow_deferred_fp = {CVAR_SAVE, "r_shadow_deferred_fp", "0", "use 16bit (1) or 32bit (2) floating point for accumulation of image-based lighting"};
286 cvar_t r_shadow_usenormalmap = {CVAR_SAVE, "r_shadow_usenormalmap", "1", "enables use of directional shading on lights"};
287 cvar_t r_shadow_gloss = {CVAR_SAVE, "r_shadow_gloss", "1", "0 disables gloss (specularity) rendering, 1 uses gloss if textures are found, 2 forces a flat metallic specular effect on everything without textures (similar to tenebrae)"};
288 cvar_t r_shadow_gloss2intensity = {0, "r_shadow_gloss2intensity", "0.125", "how bright the forced flat gloss should look if r_shadow_gloss is 2"};
289 cvar_t r_shadow_glossintensity = {0, "r_shadow_glossintensity", "1", "how bright textured glossmaps should look if r_shadow_gloss is 1 or 2"};
290 cvar_t r_shadow_glossexponent = {0, "r_shadow_glossexponent", "32", "how 'sharp' the gloss should appear (specular power)"};
291 cvar_t r_shadow_gloss2exponent = {0, "r_shadow_gloss2exponent", "32", "same as r_shadow_glossexponent but for forced gloss (gloss 2) surfaces"};
292 cvar_t r_shadow_glossexact = {0, "r_shadow_glossexact", "0", "use exact reflection math for gloss (slightly slower, but should look a tad better)"};
293 cvar_t r_shadow_lightattenuationdividebias = {0, "r_shadow_lightattenuationdividebias", "1", "changes attenuation texture generation"};
294 cvar_t r_shadow_lightattenuationlinearscale = {0, "r_shadow_lightattenuationlinearscale", "2", "changes attenuation texture generation"};
295 cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1", "renders all world lights brighter or darker"};
296 cvar_t r_shadow_lightradiusscale = {0, "r_shadow_lightradiusscale", "1", "renders all world lights larger or smaller"};
297 cvar_t r_shadow_projectdistance = {0, "r_shadow_projectdistance", "0", "how far to cast shadows"};
298 cvar_t r_shadow_frontsidecasting = {0, "r_shadow_frontsidecasting", "1", "whether to cast shadows from illuminated triangles (front side of model) or unlit triangles (back side of model)"};
299 cvar_t r_shadow_realtime_dlight = {CVAR_SAVE, "r_shadow_realtime_dlight", "1", "enables rendering of dynamic lights such as explosions and rocket light"};
300 cvar_t r_shadow_realtime_dlight_shadows = {CVAR_SAVE, "r_shadow_realtime_dlight_shadows", "1", "enables rendering of shadows from dynamic lights"};
301 cvar_t r_shadow_realtime_dlight_svbspculling = {0, "r_shadow_realtime_dlight_svbspculling", "0", "enables svbsp optimization on dynamic lights (very slow!)"};
302 cvar_t r_shadow_realtime_dlight_portalculling = {0, "r_shadow_realtime_dlight_portalculling", "0", "enables portal optimization on dynamic lights (slow!)"};
303 cvar_t r_shadow_realtime_world = {CVAR_SAVE, "r_shadow_realtime_world", "0", "enables rendering of full world lighting (whether loaded from the map, or a .rtlights file, or a .ent file, or a .lights file produced by hlight)"};
304 cvar_t r_shadow_realtime_world_lightmaps = {CVAR_SAVE, "r_shadow_realtime_world_lightmaps", "0", "brightness to render lightmaps when using full world lighting, try 0.5 for a tenebrae-like appearance"};
305 cvar_t r_shadow_realtime_world_shadows = {CVAR_SAVE, "r_shadow_realtime_world_shadows", "1", "enables rendering of shadows from world lights"};
306 cvar_t r_shadow_realtime_world_compile = {0, "r_shadow_realtime_world_compile", "1", "enables compilation of world lights for higher performance rendering"};
307 cvar_t r_shadow_realtime_world_compileshadow = {0, "r_shadow_realtime_world_compileshadow", "1", "enables compilation of shadows from world lights for higher performance rendering"};
308 cvar_t r_shadow_realtime_world_compilesvbsp = {0, "r_shadow_realtime_world_compilesvbsp", "1", "enables svbsp optimization during compilation (slower than compileportalculling but more exact)"};
309 cvar_t r_shadow_realtime_world_compileportalculling = {0, "r_shadow_realtime_world_compileportalculling", "0", "enables portal-based culling optimization during compilation (overrides compilesvbsp)"};
310 cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1", "use scissor optimization of light rendering (restricts rendering to the portion of the screen affected by the light)"};
311 cvar_t r_shadow_shadowmapping = {CVAR_SAVE, "r_shadow_shadowmapping", "0", "enables use of shadowmapping (depth texture sampling) instead of stencil shadow volumes, requires gl_fbo 1"};
312 cvar_t r_shadow_shadowmapping_texturetype = {CVAR_SAVE, "r_shadow_shadowmapping_texturetype", "-1", "shadowmap texture types: -1 = auto-select, 0 = 2D, 1 = rectangle, 2 = cubemap"};
313 cvar_t r_shadow_shadowmapping_filterquality = {CVAR_SAVE, "r_shadow_shadowmapping_filterquality", "-1", "shadowmap filter modes: -1 = auto-select, 0 = no filtering, 1 = bilinear, 2 = bilinear 2x2 blur (fast), 3 = 3x3 blur (moderate), 4 = 4x4 blur (slow)"};
314 cvar_t r_shadow_shadowmapping_depthbits = {CVAR_SAVE, "r_shadow_shadowmapping_depthbits", "24", "requested minimum shadowmap texture depth bits"};
315 cvar_t r_shadow_shadowmapping_vsdct = {CVAR_SAVE, "r_shadow_shadowmapping_vsdct", "1", "enables use of virtual shadow depth cube texture"};
316 cvar_t r_shadow_shadowmapping_minsize = {CVAR_SAVE, "r_shadow_shadowmapping_minsize", "32", "shadowmap size limit"};
317 cvar_t r_shadow_shadowmapping_maxsize = {CVAR_SAVE, "r_shadow_shadowmapping_maxsize", "512", "shadowmap size limit"};
318 cvar_t r_shadow_shadowmapping_precision = {CVAR_SAVE, "r_shadow_shadowmapping_precision", "1", "makes shadowmaps have a maximum resolution of this number of pixels per light source radius unit such that, for example, at precision 0.5 a light with radius 200 will have a maximum resolution of 100 pixels"};
319 //cvar_t r_shadow_shadowmapping_lod_bias = {CVAR_SAVE, "r_shadow_shadowmapping_lod_bias", "16", "shadowmap size bias"};
320 //cvar_t r_shadow_shadowmapping_lod_scale = {CVAR_SAVE, "r_shadow_shadowmapping_lod_scale", "128", "shadowmap size scaling parameter"};
321 cvar_t r_shadow_shadowmapping_bordersize = {CVAR_SAVE, "r_shadow_shadowmapping_bordersize", "4", "shadowmap size bias for filtering"};
322 cvar_t r_shadow_shadowmapping_nearclip = {CVAR_SAVE, "r_shadow_shadowmapping_nearclip", "1", "shadowmap nearclip in world units"};
323 cvar_t r_shadow_shadowmapping_bias = {CVAR_SAVE, "r_shadow_shadowmapping_bias", "0.03", "shadowmap bias parameter (this is multiplied by nearclip * 1024 / lodsize)"};
324 cvar_t r_shadow_shadowmapping_polygonfactor = {CVAR_SAVE, "r_shadow_shadowmapping_polygonfactor", "2", "slope-dependent shadowmapping bias"};
325 cvar_t r_shadow_shadowmapping_polygonoffset = {CVAR_SAVE, "r_shadow_shadowmapping_polygonoffset", "0", "constant shadowmapping bias"};
326 cvar_t r_shadow_polygonfactor = {0, "r_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
327 cvar_t r_shadow_polygonoffset = {0, "r_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"};
328 cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1", "use 3D voxel textures for spherical attenuation rather than cylindrical (does not affect OpenGL 2.0 render path)"};
329 cvar_t r_coronas = {CVAR_SAVE, "r_coronas", "1", "brightness of corona flare effects around certain lights, 0 disables corona effects"};
330 cvar_t r_coronas_occlusionsizescale = {CVAR_SAVE, "r_coronas_occlusionsizescale", "0.1", "size of light source for corona occlusion checksm the proportion of hidden pixels controls corona intensity"};
331 cvar_t r_coronas_occlusionquery = {CVAR_SAVE, "r_coronas_occlusionquery", "1", "use GL_ARB_occlusion_query extension if supported (fades coronas according to visibility)"};
332 cvar_t gl_flashblend = {CVAR_SAVE, "gl_flashblend", "0", "render bright coronas for dynamic lights instead of actual lighting, fast but ugly"};
333 cvar_t gl_ext_separatestencil = {0, "gl_ext_separatestencil", "1", "make use of OpenGL 2.0 glStencilOpSeparate or GL_ATI_separate_stencil extension"};
334 cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1", "make use of GL_EXT_stenciltwoside extension (NVIDIA only)"};
335 cvar_t r_editlights = {0, "r_editlights", "0", "enables .rtlights file editing mode"};
336 cvar_t r_editlights_cursordistance = {0, "r_editlights_cursordistance", "1024", "maximum distance of cursor from eye"};
337 cvar_t r_editlights_cursorpushback = {0, "r_editlights_cursorpushback", "0", "how far to pull the cursor back toward the eye"};
338 cvar_t r_editlights_cursorpushoff = {0, "r_editlights_cursorpushoff", "4", "how far to push the cursor off the impacted surface"};
339 cvar_t r_editlights_cursorgrid = {0, "r_editlights_cursorgrid", "4", "snaps cursor to this grid size"};
340 cvar_t r_editlights_quakelightsizescale = {CVAR_SAVE, "r_editlights_quakelightsizescale", "1", "changes size of light entities loaded from a map"};
341
342 // note the table actually includes one more value, just to avoid the need to clamp the distance index due to minor math error
343 #define ATTENTABLESIZE 256
344 // 1D gradient, 2D circle and 3D sphere attenuation textures
345 #define ATTEN1DSIZE 32
346 #define ATTEN2DSIZE 64
347 #define ATTEN3DSIZE 32
348
349 static float r_shadow_attendividebias; // r_shadow_lightattenuationdividebias
350 static float r_shadow_attenlinearscale; // r_shadow_lightattenuationlinearscale
351 static float r_shadow_attentable[ATTENTABLESIZE+1];
352
353 rtlight_t *r_shadow_compilingrtlight;
354 static memexpandablearray_t r_shadow_worldlightsarray;
355 dlight_t *r_shadow_selectedlight;
356 dlight_t r_shadow_bufferlight;
357 vec3_t r_editlights_cursorlocation;
358 qboolean r_editlights_lockcursor;
359
360 extern int con_vislines;
361
362 void R_Shadow_UncompileWorldLights(void);
363 void R_Shadow_ClearWorldLights(void);
364 void R_Shadow_SaveWorldLights(void);
365 void R_Shadow_LoadWorldLights(void);
366 void R_Shadow_LoadLightsFile(void);
367 void R_Shadow_LoadWorldLightsFromMap_LightArghliteTyrlite(void);
368 void R_Shadow_EditLights_Reload_f(void);
369 void R_Shadow_ValidateCvars(void);
370 static void R_Shadow_MakeTextures(void);
371
372 #define EDLIGHTSPRSIZE                  8
373 skinframe_t *r_editlights_sprcursor;
374 skinframe_t *r_editlights_sprlight;
375 skinframe_t *r_editlights_sprnoshadowlight;
376 skinframe_t *r_editlights_sprcubemaplight;
377 skinframe_t *r_editlights_sprcubemapnoshadowlight;
378 skinframe_t *r_editlights_sprselection;
379
380 void R_Shadow_SetShadowMode(void)
381 {
382         r_shadow_shadowmapmaxsize = bound(1, r_shadow_shadowmapping_maxsize.integer, (int)vid.maxtexturesize_2d / 4);
383         r_shadow_shadowmapvsdct = r_shadow_shadowmapping_vsdct.integer != 0;
384         r_shadow_shadowmapfilterquality = r_shadow_shadowmapping_filterquality.integer;
385         r_shadow_shadowmaptexturetype = r_shadow_shadowmapping_texturetype.integer;
386         r_shadow_shadowmapdepthbits = r_shadow_shadowmapping_depthbits.integer;
387         r_shadow_shadowmapborder = bound(0, r_shadow_shadowmapping_bordersize.integer, 16);
388         r_shadow_shadowmaplod = -1;
389         r_shadow_shadowmapsize = 0;
390         r_shadow_shadowmapsampler = false;
391         r_shadow_shadowmappcf = 0;
392         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
393         if ((r_shadow_shadowmapping.integer || r_shadow_deferred.integer) && vid.support.ext_framebuffer_object)
394         {
395                 switch(vid.renderpath)
396                 {
397                 case RENDERPATH_GL20:
398                         if(r_shadow_shadowmapfilterquality < 0)
399                         {
400                                 if(vid.support.amd_texture_texture4 || vid.support.arb_texture_gather)
401                                         r_shadow_shadowmappcf = 1;
402                                 else if(strstr(gl_vendor, "NVIDIA") || strstr(gl_renderer, "Radeon HD")) 
403                                 {
404                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
405                                         r_shadow_shadowmappcf = 1;
406                                 }
407                                 else if(strstr(gl_vendor, "ATI")) 
408                                         r_shadow_shadowmappcf = 1;
409                                 else 
410                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
411                         }
412                         else 
413                         {
414                                 switch (r_shadow_shadowmapfilterquality)
415                                 {
416                                 case 1:
417                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
418                                         break;
419                                 case 2:
420                                         r_shadow_shadowmapsampler = vid.support.arb_shadow;
421                                         r_shadow_shadowmappcf = 1;
422                                         break;
423                                 case 3:
424                                         r_shadow_shadowmappcf = 1;
425                                         break;
426                                 case 4:
427                                         r_shadow_shadowmappcf = 2;
428                                         break;
429                                 }
430                         }
431                         switch (r_shadow_shadowmaptexturetype)
432                         {
433                         case 0:
434                                 r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
435                                 break;
436                         case 1:
437                                 r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
438                                 break;
439                         case 2:
440                                 r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE;
441                                 break;
442                         default:
443                                 if((vid.support.amd_texture_texture4 || vid.support.arb_texture_gather) && r_shadow_shadowmappcf && !r_shadow_shadowmapsampler)
444                                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
445                                 else if(vid.support.arb_texture_rectangle) 
446                                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE;
447                                 else
448                                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
449                                 break;
450                         }
451                         // Cg has very little choice in depth texture sampling
452                         if (vid.cgcontext)
453                         {
454                                 r_shadow_shadowmapsampler = false;
455                                 r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
456                         }
457                         break;
458                 case RENDERPATH_CGGL:
459                 case RENDERPATH_D3D9:
460                 case RENDERPATH_D3D10:
461                 case RENDERPATH_D3D11:
462                         r_shadow_shadowmapsampler = false;
463                         r_shadow_shadowmappcf = 1;
464                         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_SHADOWMAP2D;
465                         break;
466                 case RENDERPATH_GL13:
467                         break;
468                 case RENDERPATH_GL11:
469                         break;
470                 }
471         }
472 }
473
474 qboolean R_Shadow_ShadowMappingEnabled(void)
475 {
476         switch (r_shadow_shadowmode)
477         {
478         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
479         case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
480         case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
481                 return true;
482         default:
483                 return false;
484         }
485 }
486
487 void R_Shadow_FreeShadowMaps(void)
488 {
489         int i;
490
491         R_Shadow_SetShadowMode();
492
493         R_Mesh_DestroyFramebufferObject(r_shadow_fborectangle);
494
495         R_Mesh_DestroyFramebufferObject(r_shadow_fbo2d);
496         for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
497                 R_Mesh_DestroyFramebufferObject(r_shadow_fbocubeside[i]);
498
499         r_shadow_fborectangle = 0;
500         r_shadow_fbo2d = 0;
501         memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
502
503         if (r_shadow_shadowmaprectangletexture)
504                 R_FreeTexture(r_shadow_shadowmaprectangletexture);
505         r_shadow_shadowmaprectangletexture = NULL;
506
507         if (r_shadow_shadowmap2dtexture)
508                 R_FreeTexture(r_shadow_shadowmap2dtexture);
509         r_shadow_shadowmap2dtexture = NULL;
510
511         for (i = 0;i < R_SHADOW_SHADOWMAP_NUMCUBEMAPS;i++)
512                 if (r_shadow_shadowmapcubetexture[i])
513                         R_FreeTexture(r_shadow_shadowmapcubetexture[i]);
514         memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
515
516         if (r_shadow_shadowmap2dcolortexture)
517                 R_FreeTexture(r_shadow_shadowmap2dcolortexture);
518         r_shadow_shadowmap2dcolortexture = NULL;
519
520         if (r_shadow_shadowmapvsdcttexture)
521                 R_FreeTexture(r_shadow_shadowmapvsdcttexture);
522         r_shadow_shadowmapvsdcttexture = NULL;
523 }
524
525 void r_shadow_start(void)
526 {
527         // allocate vertex processing arrays
528         r_shadow_attenuationgradienttexture = NULL;
529         r_shadow_attenuation2dtexture = NULL;
530         r_shadow_attenuation3dtexture = NULL;
531         r_shadow_shadowmode = R_SHADOW_SHADOWMODE_STENCIL;
532         r_shadow_shadowmaprectangletexture = NULL;
533         r_shadow_shadowmap2dtexture = NULL;
534         memset(r_shadow_shadowmapcubetexture, 0, sizeof(r_shadow_shadowmapcubetexture));
535         r_shadow_shadowmap2dcolortexture = NULL;
536         r_shadow_shadowmapvsdcttexture = NULL;
537         r_shadow_shadowmapmaxsize = 0;
538         r_shadow_shadowmapsize = 0;
539         r_shadow_shadowmaplod = 0;
540         r_shadow_shadowmapfilterquality = -1;
541         r_shadow_shadowmaptexturetype = -1;
542         r_shadow_shadowmapdepthbits = 0;
543         r_shadow_shadowmapvsdct = false;
544         r_shadow_shadowmapsampler = false;
545         r_shadow_shadowmappcf = 0;
546         r_shadow_fborectangle = 0;
547         r_shadow_fbo2d = 0;
548         memset(r_shadow_fbocubeside, 0, sizeof(r_shadow_fbocubeside));
549
550         R_Shadow_FreeShadowMaps();
551
552         r_shadow_texturepool = NULL;
553         r_shadow_filters_texturepool = NULL;
554         R_Shadow_ValidateCvars();
555         R_Shadow_MakeTextures();
556         maxshadowtriangles = 0;
557         shadowelements = NULL;
558         maxshadowvertices = 0;
559         shadowvertex3f = NULL;
560         maxvertexupdate = 0;
561         vertexupdate = NULL;
562         vertexremap = NULL;
563         vertexupdatenum = 0;
564         maxshadowmark = 0;
565         numshadowmark = 0;
566         shadowmark = NULL;
567         shadowmarklist = NULL;
568         shadowmarkcount = 0;
569         maxshadowsides = 0;
570         numshadowsides = 0;
571         shadowsides = NULL;
572         shadowsideslist = NULL;
573         r_shadow_buffer_numleafpvsbytes = 0;
574         r_shadow_buffer_visitingleafpvs = NULL;
575         r_shadow_buffer_leafpvs = NULL;
576         r_shadow_buffer_leaflist = NULL;
577         r_shadow_buffer_numsurfacepvsbytes = 0;
578         r_shadow_buffer_surfacepvs = NULL;
579         r_shadow_buffer_surfacelist = NULL;
580         r_shadow_buffer_surfacesides = NULL;
581         r_shadow_buffer_numshadowtrispvsbytes = 0;
582         r_shadow_buffer_shadowtrispvs = NULL;
583         r_shadow_buffer_numlighttrispvsbytes = 0;
584         r_shadow_buffer_lighttrispvs = NULL;
585
586         r_shadow_usingdeferredprepass = false;
587         r_shadow_prepass_width = r_shadow_prepass_height = 0;
588 }
589
590 static void R_Shadow_FreeDeferred(void);
591 void r_shadow_shutdown(void)
592 {
593         CHECKGLERROR
594         R_Shadow_UncompileWorldLights();
595
596         R_Shadow_FreeShadowMaps();
597
598         r_shadow_usingdeferredprepass = false;
599         if (r_shadow_prepass_width)
600                 R_Shadow_FreeDeferred();
601         r_shadow_prepass_width = r_shadow_prepass_height = 0;
602
603         CHECKGLERROR
604         r_shadow_attenuationgradienttexture = NULL;
605         r_shadow_attenuation2dtexture = NULL;
606         r_shadow_attenuation3dtexture = NULL;
607         R_FreeTexturePool(&r_shadow_texturepool);
608         R_FreeTexturePool(&r_shadow_filters_texturepool);
609         maxshadowtriangles = 0;
610         if (shadowelements)
611                 Mem_Free(shadowelements);
612         shadowelements = NULL;
613         if (shadowvertex3f)
614                 Mem_Free(shadowvertex3f);
615         shadowvertex3f = NULL;
616         maxvertexupdate = 0;
617         if (vertexupdate)
618                 Mem_Free(vertexupdate);
619         vertexupdate = NULL;
620         if (vertexremap)
621                 Mem_Free(vertexremap);
622         vertexremap = NULL;
623         vertexupdatenum = 0;
624         maxshadowmark = 0;
625         numshadowmark = 0;
626         if (shadowmark)
627                 Mem_Free(shadowmark);
628         shadowmark = NULL;
629         if (shadowmarklist)
630                 Mem_Free(shadowmarklist);
631         shadowmarklist = NULL;
632         shadowmarkcount = 0;
633         maxshadowsides = 0;
634         numshadowsides = 0;
635         if (shadowsides)
636                 Mem_Free(shadowsides);
637         shadowsides = NULL;
638         if (shadowsideslist)
639                 Mem_Free(shadowsideslist);
640         shadowsideslist = NULL;
641         r_shadow_buffer_numleafpvsbytes = 0;
642         if (r_shadow_buffer_visitingleafpvs)
643                 Mem_Free(r_shadow_buffer_visitingleafpvs);
644         r_shadow_buffer_visitingleafpvs = NULL;
645         if (r_shadow_buffer_leafpvs)
646                 Mem_Free(r_shadow_buffer_leafpvs);
647         r_shadow_buffer_leafpvs = NULL;
648         if (r_shadow_buffer_leaflist)
649                 Mem_Free(r_shadow_buffer_leaflist);
650         r_shadow_buffer_leaflist = NULL;
651         r_shadow_buffer_numsurfacepvsbytes = 0;
652         if (r_shadow_buffer_surfacepvs)
653                 Mem_Free(r_shadow_buffer_surfacepvs);
654         r_shadow_buffer_surfacepvs = NULL;
655         if (r_shadow_buffer_surfacelist)
656                 Mem_Free(r_shadow_buffer_surfacelist);
657         r_shadow_buffer_surfacelist = NULL;
658         if (r_shadow_buffer_surfacesides)
659                 Mem_Free(r_shadow_buffer_surfacesides);
660         r_shadow_buffer_surfacesides = NULL;
661         r_shadow_buffer_numshadowtrispvsbytes = 0;
662         if (r_shadow_buffer_shadowtrispvs)
663                 Mem_Free(r_shadow_buffer_shadowtrispvs);
664         r_shadow_buffer_numlighttrispvsbytes = 0;
665         if (r_shadow_buffer_lighttrispvs)
666                 Mem_Free(r_shadow_buffer_lighttrispvs);
667 }
668
669 void r_shadow_newmap(void)
670 {
671         if (r_shadow_lightcorona)                 R_SkinFrame_MarkUsed(r_shadow_lightcorona);
672         if (r_editlights_sprcursor)               R_SkinFrame_MarkUsed(r_editlights_sprcursor);
673         if (r_editlights_sprlight)                R_SkinFrame_MarkUsed(r_editlights_sprlight);
674         if (r_editlights_sprnoshadowlight)        R_SkinFrame_MarkUsed(r_editlights_sprnoshadowlight);
675         if (r_editlights_sprcubemaplight)         R_SkinFrame_MarkUsed(r_editlights_sprcubemaplight);
676         if (r_editlights_sprcubemapnoshadowlight) R_SkinFrame_MarkUsed(r_editlights_sprcubemapnoshadowlight);
677         if (r_editlights_sprselection)            R_SkinFrame_MarkUsed(r_editlights_sprselection);
678         if (strncmp(cl.worldname, r_shadow_mapname, sizeof(r_shadow_mapname)))
679                 R_Shadow_EditLights_Reload_f();
680 }
681
682 void R_Shadow_Init(void)
683 {
684         Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture);
685         Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap);
686         Cvar_RegisterVariable(&r_shadow_usenormalmap);
687         Cvar_RegisterVariable(&r_shadow_debuglight);
688         Cvar_RegisterVariable(&r_shadow_deferred);
689         Cvar_RegisterVariable(&r_shadow_deferred_8bitrange);
690 //      Cvar_RegisterVariable(&r_shadow_deferred_fp);
691         Cvar_RegisterVariable(&r_shadow_gloss);
692         Cvar_RegisterVariable(&r_shadow_gloss2intensity);
693         Cvar_RegisterVariable(&r_shadow_glossintensity);
694         Cvar_RegisterVariable(&r_shadow_glossexponent);
695         Cvar_RegisterVariable(&r_shadow_gloss2exponent);
696         Cvar_RegisterVariable(&r_shadow_glossexact);
697         Cvar_RegisterVariable(&r_shadow_lightattenuationdividebias);
698         Cvar_RegisterVariable(&r_shadow_lightattenuationlinearscale);
699         Cvar_RegisterVariable(&r_shadow_lightintensityscale);
700         Cvar_RegisterVariable(&r_shadow_lightradiusscale);
701         Cvar_RegisterVariable(&r_shadow_projectdistance);
702         Cvar_RegisterVariable(&r_shadow_frontsidecasting);
703         Cvar_RegisterVariable(&r_shadow_realtime_dlight);
704         Cvar_RegisterVariable(&r_shadow_realtime_dlight_shadows);
705         Cvar_RegisterVariable(&r_shadow_realtime_dlight_svbspculling);
706         Cvar_RegisterVariable(&r_shadow_realtime_dlight_portalculling);
707         Cvar_RegisterVariable(&r_shadow_realtime_world);
708         Cvar_RegisterVariable(&r_shadow_realtime_world_lightmaps);
709         Cvar_RegisterVariable(&r_shadow_realtime_world_shadows);
710         Cvar_RegisterVariable(&r_shadow_realtime_world_compile);
711         Cvar_RegisterVariable(&r_shadow_realtime_world_compileshadow);
712         Cvar_RegisterVariable(&r_shadow_realtime_world_compilesvbsp);
713         Cvar_RegisterVariable(&r_shadow_realtime_world_compileportalculling);
714         Cvar_RegisterVariable(&r_shadow_scissor);
715         Cvar_RegisterVariable(&r_shadow_shadowmapping);
716         Cvar_RegisterVariable(&r_shadow_shadowmapping_vsdct);
717         Cvar_RegisterVariable(&r_shadow_shadowmapping_texturetype);
718         Cvar_RegisterVariable(&r_shadow_shadowmapping_filterquality);
719         Cvar_RegisterVariable(&r_shadow_shadowmapping_depthbits);
720         Cvar_RegisterVariable(&r_shadow_shadowmapping_precision);
721         Cvar_RegisterVariable(&r_shadow_shadowmapping_maxsize);
722         Cvar_RegisterVariable(&r_shadow_shadowmapping_minsize);
723 //      Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_bias);
724 //      Cvar_RegisterVariable(&r_shadow_shadowmapping_lod_scale);
725         Cvar_RegisterVariable(&r_shadow_shadowmapping_bordersize);
726         Cvar_RegisterVariable(&r_shadow_shadowmapping_nearclip);
727         Cvar_RegisterVariable(&r_shadow_shadowmapping_bias);
728         Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonfactor);
729         Cvar_RegisterVariable(&r_shadow_shadowmapping_polygonoffset);
730         Cvar_RegisterVariable(&r_shadow_polygonfactor);
731         Cvar_RegisterVariable(&r_shadow_polygonoffset);
732         Cvar_RegisterVariable(&r_shadow_texture3d);
733         Cvar_RegisterVariable(&r_coronas);
734         Cvar_RegisterVariable(&r_coronas_occlusionsizescale);
735         Cvar_RegisterVariable(&r_coronas_occlusionquery);
736         Cvar_RegisterVariable(&gl_flashblend);
737         Cvar_RegisterVariable(&gl_ext_separatestencil);
738         Cvar_RegisterVariable(&gl_ext_stenciltwoside);
739         if (gamemode == GAME_TENEBRAE)
740         {
741                 Cvar_SetValue("r_shadow_gloss", 2);
742                 Cvar_SetValue("r_shadow_bumpscale_basetexture", 4);
743         }
744         R_Shadow_EditLights_Init();
745         Mem_ExpandableArray_NewArray(&r_shadow_worldlightsarray, r_main_mempool, sizeof(dlight_t), 128);
746         maxshadowtriangles = 0;
747         shadowelements = NULL;
748         maxshadowvertices = 0;
749         shadowvertex3f = NULL;
750         maxvertexupdate = 0;
751         vertexupdate = NULL;
752         vertexremap = NULL;
753         vertexupdatenum = 0;
754         maxshadowmark = 0;
755         numshadowmark = 0;
756         shadowmark = NULL;
757         shadowmarklist = NULL;
758         shadowmarkcount = 0;
759         maxshadowsides = 0;
760         numshadowsides = 0;
761         shadowsides = NULL;
762         shadowsideslist = NULL;
763         r_shadow_buffer_numleafpvsbytes = 0;
764         r_shadow_buffer_visitingleafpvs = NULL;
765         r_shadow_buffer_leafpvs = NULL;
766         r_shadow_buffer_leaflist = NULL;
767         r_shadow_buffer_numsurfacepvsbytes = 0;
768         r_shadow_buffer_surfacepvs = NULL;
769         r_shadow_buffer_surfacelist = NULL;
770         r_shadow_buffer_surfacesides = NULL;
771         r_shadow_buffer_shadowtrispvs = NULL;
772         r_shadow_buffer_lighttrispvs = NULL;
773         R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap, NULL, NULL);
774 }
775
776 matrix4x4_t matrix_attenuationxyz =
777 {
778         {
779                 {0.5, 0.0, 0.0, 0.5},
780                 {0.0, 0.5, 0.0, 0.5},
781                 {0.0, 0.0, 0.5, 0.5},
782                 {0.0, 0.0, 0.0, 1.0}
783         }
784 };
785
786 matrix4x4_t matrix_attenuationz =
787 {
788         {
789                 {0.0, 0.0, 0.5, 0.5},
790                 {0.0, 0.0, 0.0, 0.5},
791                 {0.0, 0.0, 0.0, 0.5},
792                 {0.0, 0.0, 0.0, 1.0}
793         }
794 };
795
796 void R_Shadow_ResizeShadowArrays(int numvertices, int numtriangles, int vertscale, int triscale)
797 {
798         numvertices = ((numvertices + 255) & ~255) * vertscale;
799         numtriangles = ((numtriangles + 255) & ~255) * triscale;
800         // make sure shadowelements is big enough for this volume
801         if (maxshadowtriangles < numtriangles)
802         {
803                 maxshadowtriangles = numtriangles;
804                 if (shadowelements)
805                         Mem_Free(shadowelements);
806                 shadowelements = (int *)Mem_Alloc(r_main_mempool, maxshadowtriangles * sizeof(int[3]));
807         }
808         // make sure shadowvertex3f is big enough for this volume
809         if (maxshadowvertices < numvertices)
810         {
811                 maxshadowvertices = numvertices;
812                 if (shadowvertex3f)
813                         Mem_Free(shadowvertex3f);
814                 shadowvertex3f = (float *)Mem_Alloc(r_main_mempool, maxshadowvertices * sizeof(float[3]));
815         }
816 }
817
818 static void R_Shadow_EnlargeLeafSurfaceTrisBuffer(int numleafs, int numsurfaces, int numshadowtriangles, int numlighttriangles)
819 {
820         int numleafpvsbytes = (((numleafs + 7) >> 3) + 255) & ~255;
821         int numsurfacepvsbytes = (((numsurfaces + 7) >> 3) + 255) & ~255;
822         int numshadowtrispvsbytes = (((numshadowtriangles + 7) >> 3) + 255) & ~255;
823         int numlighttrispvsbytes = (((numlighttriangles + 7) >> 3) + 255) & ~255;
824         if (r_shadow_buffer_numleafpvsbytes < numleafpvsbytes)
825         {
826                 if (r_shadow_buffer_visitingleafpvs)
827                         Mem_Free(r_shadow_buffer_visitingleafpvs);
828                 if (r_shadow_buffer_leafpvs)
829                         Mem_Free(r_shadow_buffer_leafpvs);
830                 if (r_shadow_buffer_leaflist)
831                         Mem_Free(r_shadow_buffer_leaflist);
832                 r_shadow_buffer_numleafpvsbytes = numleafpvsbytes;
833                 r_shadow_buffer_visitingleafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
834                 r_shadow_buffer_leafpvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes);
835                 r_shadow_buffer_leaflist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numleafpvsbytes * 8 * sizeof(*r_shadow_buffer_leaflist));
836         }
837         if (r_shadow_buffer_numsurfacepvsbytes < numsurfacepvsbytes)
838         {
839                 if (r_shadow_buffer_surfacepvs)
840                         Mem_Free(r_shadow_buffer_surfacepvs);
841                 if (r_shadow_buffer_surfacelist)
842                         Mem_Free(r_shadow_buffer_surfacelist);
843                 if (r_shadow_buffer_surfacesides)
844                         Mem_Free(r_shadow_buffer_surfacesides);
845                 r_shadow_buffer_numsurfacepvsbytes = numsurfacepvsbytes;
846                 r_shadow_buffer_surfacepvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes);
847                 r_shadow_buffer_surfacelist = (int *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes * 8 * sizeof(*r_shadow_buffer_surfacelist));
848                 r_shadow_buffer_surfacesides = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numsurfacepvsbytes * 8 * sizeof(*r_shadow_buffer_surfacelist));
849         }
850         if (r_shadow_buffer_numshadowtrispvsbytes < numshadowtrispvsbytes)
851         {
852                 if (r_shadow_buffer_shadowtrispvs)
853                         Mem_Free(r_shadow_buffer_shadowtrispvs);
854                 r_shadow_buffer_numshadowtrispvsbytes = numshadowtrispvsbytes;
855                 r_shadow_buffer_shadowtrispvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numshadowtrispvsbytes);
856         }
857         if (r_shadow_buffer_numlighttrispvsbytes < numlighttrispvsbytes)
858         {
859                 if (r_shadow_buffer_lighttrispvs)
860                         Mem_Free(r_shadow_buffer_lighttrispvs);
861                 r_shadow_buffer_numlighttrispvsbytes = numlighttrispvsbytes;
862                 r_shadow_buffer_lighttrispvs = (unsigned char *)Mem_Alloc(r_main_mempool, r_shadow_buffer_numlighttrispvsbytes);
863         }
864 }
865
866 void R_Shadow_PrepareShadowMark(int numtris)
867 {
868         // make sure shadowmark is big enough for this volume
869         if (maxshadowmark < numtris)
870         {
871                 maxshadowmark = numtris;
872                 if (shadowmark)
873                         Mem_Free(shadowmark);
874                 if (shadowmarklist)
875                         Mem_Free(shadowmarklist);
876                 shadowmark = (int *)Mem_Alloc(r_main_mempool, maxshadowmark * sizeof(*shadowmark));
877                 shadowmarklist = (int *)Mem_Alloc(r_main_mempool, maxshadowmark * sizeof(*shadowmarklist));
878                 shadowmarkcount = 0;
879         }
880         shadowmarkcount++;
881         // if shadowmarkcount wrapped we clear the array and adjust accordingly
882         if (shadowmarkcount == 0)
883         {
884                 shadowmarkcount = 1;
885                 memset(shadowmark, 0, maxshadowmark * sizeof(*shadowmark));
886         }
887         numshadowmark = 0;
888 }
889
890 void R_Shadow_PrepareShadowSides(int numtris)
891 {
892     if (maxshadowsides < numtris)
893     {
894         maxshadowsides = numtris;
895         if (shadowsides)
896                         Mem_Free(shadowsides);
897                 if (shadowsideslist)
898                         Mem_Free(shadowsideslist);
899                 shadowsides = (unsigned char *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsides));
900                 shadowsideslist = (int *)Mem_Alloc(r_main_mempool, maxshadowsides * sizeof(*shadowsideslist));
901         }
902         numshadowsides = 0;
903 }
904
905 static int R_Shadow_ConstructShadowVolume_ZFail(int innumvertices, int innumtris, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *projectorigin, const float *projectdirection, float projectdistance, int numshadowmarktris, const int *shadowmarktris)
906 {
907         int i, j;
908         int outtriangles = 0, outvertices = 0;
909         const int *element;
910         const float *vertex;
911         float ratio, direction[3], projectvector[3];
912
913         if (projectdirection)
914                 VectorScale(projectdirection, projectdistance, projectvector);
915         else
916                 VectorClear(projectvector);
917
918         // create the vertices
919         if (projectdirection)
920         {
921                 for (i = 0;i < numshadowmarktris;i++)
922                 {
923                         element = inelement3i + shadowmarktris[i] * 3;
924                         for (j = 0;j < 3;j++)
925                         {
926                                 if (vertexupdate[element[j]] != vertexupdatenum)
927                                 {
928                                         vertexupdate[element[j]] = vertexupdatenum;
929                                         vertexremap[element[j]] = outvertices;
930                                         vertex = invertex3f + element[j] * 3;
931                                         // project one copy of the vertex according to projectvector
932                                         VectorCopy(vertex, outvertex3f);
933                                         VectorAdd(vertex, projectvector, (outvertex3f + 3));
934                                         outvertex3f += 6;
935                                         outvertices += 2;
936                                 }
937                         }
938                 }
939         }
940         else
941         {
942                 for (i = 0;i < numshadowmarktris;i++)
943                 {
944                         element = inelement3i + shadowmarktris[i] * 3;
945                         for (j = 0;j < 3;j++)
946                         {
947                                 if (vertexupdate[element[j]] != vertexupdatenum)
948                                 {
949                                         vertexupdate[element[j]] = vertexupdatenum;
950                                         vertexremap[element[j]] = outvertices;
951                                         vertex = invertex3f + element[j] * 3;
952                                         // project one copy of the vertex to the sphere radius of the light
953                                         // (FIXME: would projecting it to the light box be better?)
954                                         VectorSubtract(vertex, projectorigin, direction);
955                                         ratio = projectdistance / VectorLength(direction);
956                                         VectorCopy(vertex, outvertex3f);
957                                         VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
958                                         outvertex3f += 6;
959                                         outvertices += 2;
960                                 }
961                         }
962                 }
963         }
964
965         if (r_shadow_frontsidecasting.integer)
966         {
967                 for (i = 0;i < numshadowmarktris;i++)
968                 {
969                         int remappedelement[3];
970                         int markindex;
971                         const int *neighbortriangle;
972
973                         markindex = shadowmarktris[i] * 3;
974                         element = inelement3i + markindex;
975                         neighbortriangle = inneighbor3i + markindex;
976                         // output the front and back triangles
977                         outelement3i[0] = vertexremap[element[0]];
978                         outelement3i[1] = vertexremap[element[1]];
979                         outelement3i[2] = vertexremap[element[2]];
980                         outelement3i[3] = vertexremap[element[2]] + 1;
981                         outelement3i[4] = vertexremap[element[1]] + 1;
982                         outelement3i[5] = vertexremap[element[0]] + 1;
983
984                         outelement3i += 6;
985                         outtriangles += 2;
986                         // output the sides (facing outward from this triangle)
987                         if (shadowmark[neighbortriangle[0]] != shadowmarkcount)
988                         {
989                                 remappedelement[0] = vertexremap[element[0]];
990                                 remappedelement[1] = vertexremap[element[1]];
991                                 outelement3i[0] = remappedelement[1];
992                                 outelement3i[1] = remappedelement[0];
993                                 outelement3i[2] = remappedelement[0] + 1;
994                                 outelement3i[3] = remappedelement[1];
995                                 outelement3i[4] = remappedelement[0] + 1;
996                                 outelement3i[5] = remappedelement[1] + 1;
997
998                                 outelement3i += 6;
999                                 outtriangles += 2;
1000                         }
1001                         if (shadowmark[neighbortriangle[1]] != shadowmarkcount)
1002                         {
1003                                 remappedelement[1] = vertexremap[element[1]];
1004                                 remappedelement[2] = vertexremap[element[2]];
1005                                 outelement3i[0] = remappedelement[2];
1006                                 outelement3i[1] = remappedelement[1];
1007                                 outelement3i[2] = remappedelement[1] + 1;
1008                                 outelement3i[3] = remappedelement[2];
1009                                 outelement3i[4] = remappedelement[1] + 1;
1010                                 outelement3i[5] = remappedelement[2] + 1;
1011
1012                                 outelement3i += 6;
1013                                 outtriangles += 2;
1014                         }
1015                         if (shadowmark[neighbortriangle[2]] != shadowmarkcount)
1016                         {
1017                                 remappedelement[0] = vertexremap[element[0]];
1018                                 remappedelement[2] = vertexremap[element[2]];
1019                                 outelement3i[0] = remappedelement[0];
1020                                 outelement3i[1] = remappedelement[2];
1021                                 outelement3i[2] = remappedelement[2] + 1;
1022                                 outelement3i[3] = remappedelement[0];
1023                                 outelement3i[4] = remappedelement[2] + 1;
1024                                 outelement3i[5] = remappedelement[0] + 1;
1025
1026                                 outelement3i += 6;
1027                                 outtriangles += 2;
1028                         }
1029                 }
1030         }
1031         else
1032         {
1033                 for (i = 0;i < numshadowmarktris;i++)
1034                 {
1035                         int remappedelement[3];
1036                         int markindex;
1037                         const int *neighbortriangle;
1038
1039                         markindex = shadowmarktris[i] * 3;
1040                         element = inelement3i + markindex;
1041                         neighbortriangle = inneighbor3i + markindex;
1042                         // output the front and back triangles
1043                         outelement3i[0] = vertexremap[element[2]];
1044                         outelement3i[1] = vertexremap[element[1]];
1045                         outelement3i[2] = vertexremap[element[0]];
1046                         outelement3i[3] = vertexremap[element[0]] + 1;
1047                         outelement3i[4] = vertexremap[element[1]] + 1;
1048                         outelement3i[5] = vertexremap[element[2]] + 1;
1049
1050                         outelement3i += 6;
1051                         outtriangles += 2;
1052                         // output the sides (facing outward from this triangle)
1053                         if (shadowmark[neighbortriangle[0]] != shadowmarkcount)
1054                         {
1055                                 remappedelement[0] = vertexremap[element[0]];
1056                                 remappedelement[1] = vertexremap[element[1]];
1057                                 outelement3i[0] = remappedelement[0];
1058                                 outelement3i[1] = remappedelement[1];
1059                                 outelement3i[2] = remappedelement[1] + 1;
1060                                 outelement3i[3] = remappedelement[0];
1061                                 outelement3i[4] = remappedelement[1] + 1;
1062                                 outelement3i[5] = remappedelement[0] + 1;
1063
1064                                 outelement3i += 6;
1065                                 outtriangles += 2;
1066                         }
1067                         if (shadowmark[neighbortriangle[1]] != shadowmarkcount)
1068                         {
1069                                 remappedelement[1] = vertexremap[element[1]];
1070                                 remappedelement[2] = vertexremap[element[2]];
1071                                 outelement3i[0] = remappedelement[1];
1072                                 outelement3i[1] = remappedelement[2];
1073                                 outelement3i[2] = remappedelement[2] + 1;
1074                                 outelement3i[3] = remappedelement[1];
1075                                 outelement3i[4] = remappedelement[2] + 1;
1076                                 outelement3i[5] = remappedelement[1] + 1;
1077
1078                                 outelement3i += 6;
1079                                 outtriangles += 2;
1080                         }
1081                         if (shadowmark[neighbortriangle[2]] != shadowmarkcount)
1082                         {
1083                                 remappedelement[0] = vertexremap[element[0]];
1084                                 remappedelement[2] = vertexremap[element[2]];
1085                                 outelement3i[0] = remappedelement[2];
1086                                 outelement3i[1] = remappedelement[0];
1087                                 outelement3i[2] = remappedelement[0] + 1;
1088                                 outelement3i[3] = remappedelement[2];
1089                                 outelement3i[4] = remappedelement[0] + 1;
1090                                 outelement3i[5] = remappedelement[2] + 1;
1091
1092                                 outelement3i += 6;
1093                                 outtriangles += 2;
1094                         }
1095                 }
1096         }
1097         if (outnumvertices)
1098                 *outnumvertices = outvertices;
1099         return outtriangles;
1100 }
1101
1102 static int R_Shadow_ConstructShadowVolume_ZPass(int innumvertices, int innumtris, const int *inelement3i, const int *inneighbor3i, const float *invertex3f, int *outnumvertices, int *outelement3i, float *outvertex3f, const float *projectorigin, const float *projectdirection, float projectdistance, int numshadowmarktris, const int *shadowmarktris)
1103 {
1104         int i, j, k;
1105         int outtriangles = 0, outvertices = 0;
1106         const int *element;
1107         const float *vertex;
1108         float ratio, direction[3], projectvector[3];
1109         qboolean side[4];
1110
1111         if (projectdirection)
1112                 VectorScale(projectdirection, projectdistance, projectvector);
1113         else
1114                 VectorClear(projectvector);
1115
1116         for (i = 0;i < numshadowmarktris;i++)
1117         {
1118                 int remappedelement[3];
1119                 int markindex;
1120                 const int *neighbortriangle;
1121
1122                 markindex = shadowmarktris[i] * 3;
1123                 neighbortriangle = inneighbor3i + markindex;
1124                 side[0] = shadowmark[neighbortriangle[0]] == shadowmarkcount;
1125                 side[1] = shadowmark[neighbortriangle[1]] == shadowmarkcount;
1126                 side[2] = shadowmark[neighbortriangle[2]] == shadowmarkcount;
1127                 if (side[0] + side[1] + side[2] == 0)
1128                         continue;
1129
1130                 side[3] = side[0];
1131                 element = inelement3i + markindex;
1132
1133                 // create the vertices
1134                 for (j = 0;j < 3;j++)
1135                 {
1136                         if (side[j] + side[j+1] == 0)
1137                                 continue;
1138                         k = element[j];
1139                         if (vertexupdate[k] != vertexupdatenum)
1140                         {
1141                                 vertexupdate[k] = vertexupdatenum;
1142                                 vertexremap[k] = outvertices;
1143                                 vertex = invertex3f + k * 3;
1144                                 VectorCopy(vertex, outvertex3f);
1145                                 if (projectdirection)
1146                                 {
1147                                         // project one copy of the vertex according to projectvector
1148                                         VectorAdd(vertex, projectvector, (outvertex3f + 3));
1149                                 }
1150                                 else
1151                                 {
1152                                         // project one copy of the vertex to the sphere radius of the light
1153                                         // (FIXME: would projecting it to the light box be better?)
1154                                         VectorSubtract(vertex, projectorigin, direction);
1155                                         ratio = projectdistance / VectorLength(direction);
1156                                         VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
1157                                 }
1158                                 outvertex3f += 6;
1159                                 outvertices += 2;
1160                         }
1161                 }
1162
1163                 // output the sides (facing outward from this triangle)
1164                 if (!side[0])
1165                 {
1166                         remappedelement[0] = vertexremap[element[0]];
1167                         remappedelement[1] = vertexremap[element[1]];
1168                         outelement3i[0] = remappedelement[1];
1169                         outelement3i[1] = remappedelement[0];
1170                         outelement3i[2] = remappedelement[0] + 1;
1171                         outelement3i[3] = remappedelement[1];
1172                         outelement3i[4] = remappedelement[0] + 1;
1173                         outelement3i[5] = remappedelement[1] + 1;
1174
1175                         outelement3i += 6;
1176                         outtriangles += 2;
1177                 }
1178                 if (!side[1])
1179                 {
1180                         remappedelement[1] = vertexremap[element[1]];
1181                         remappedelement[2] = vertexremap[element[2]];
1182                         outelement3i[0] = remappedelement[2];
1183                         outelement3i[1] = remappedelement[1];
1184                         outelement3i[2] = remappedelement[1] + 1;
1185                         outelement3i[3] = remappedelement[2];
1186                         outelement3i[4] = remappedelement[1] + 1;
1187                         outelement3i[5] = remappedelement[2] + 1;
1188
1189                         outelement3i += 6;
1190                         outtriangles += 2;
1191                 }
1192                 if (!side[2])
1193                 {
1194                         remappedelement[0] = vertexremap[element[0]];
1195                         remappedelement[2] = vertexremap[element[2]];
1196                         outelement3i[0] = remappedelement[0];
1197                         outelement3i[1] = remappedelement[2];
1198                         outelement3i[2] = remappedelement[2] + 1;
1199                         outelement3i[3] = remappedelement[0];
1200                         outelement3i[4] = remappedelement[2] + 1;
1201                         outelement3i[5] = remappedelement[0] + 1;
1202
1203                         outelement3i += 6;
1204                         outtriangles += 2;
1205                 }
1206         }
1207         if (outnumvertices)
1208                 *outnumvertices = outvertices;
1209         return outtriangles;
1210 }
1211
1212 void R_Shadow_MarkVolumeFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const vec3_t projectorigin, const vec3_t projectdirection, const vec3_t lightmins, const vec3_t lightmaxs, const vec3_t surfacemins, const vec3_t surfacemaxs)
1213 {
1214         int t, tend;
1215         const int *e;
1216         const float *v[3];
1217         float normal[3];
1218         if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1219                 return;
1220         tend = firsttriangle + numtris;
1221         if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1222         {
1223                 // surface box entirely inside light box, no box cull
1224                 if (projectdirection)
1225                 {
1226                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1227                         {
1228                                 TriangleNormal(invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3, normal);
1229                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1230                                         shadowmarklist[numshadowmark++] = t;
1231                         }
1232                 }
1233                 else
1234                 {
1235                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1236                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, invertex3f + e[0] * 3, invertex3f + e[1] * 3, invertex3f + e[2] * 3))
1237                                         shadowmarklist[numshadowmark++] = t;
1238                 }
1239         }
1240         else
1241         {
1242                 // surface box not entirely inside light box, cull each triangle
1243                 if (projectdirection)
1244                 {
1245                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1246                         {
1247                                 v[0] = invertex3f + e[0] * 3;
1248                                 v[1] = invertex3f + e[1] * 3;
1249                                 v[2] = invertex3f + e[2] * 3;
1250                                 TriangleNormal(v[0], v[1], v[2], normal);
1251                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1252                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1253                                         shadowmarklist[numshadowmark++] = t;
1254                         }
1255                 }
1256                 else
1257                 {
1258                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1259                         {
1260                                 v[0] = invertex3f + e[0] * 3;
1261                                 v[1] = invertex3f + e[1] * 3;
1262                                 v[2] = invertex3f + e[2] * 3;
1263                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1264                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1265                                         shadowmarklist[numshadowmark++] = t;
1266                         }
1267                 }
1268         }
1269 }
1270
1271 qboolean R_Shadow_UseZPass(vec3_t mins, vec3_t maxs)
1272 {
1273 #if 1
1274         return false;
1275 #else
1276         if (r_shadow_compilingrtlight || !r_shadow_frontsidecasting.integer || !r_shadow_usezpassifpossible.integer)
1277                 return false;
1278         // check if the shadow volume intersects the near plane
1279         //
1280         // a ray between the eye and light origin may intersect the caster,
1281         // indicating that the shadow may touch the eye location, however we must
1282         // test the near plane (a polygon), not merely the eye location, so it is
1283         // easiest to enlarge the caster bounding shape slightly for this.
1284         // TODO
1285         return true;
1286 #endif
1287 }
1288
1289 void R_Shadow_VolumeFromList(int numverts, int numtris, const float *invertex3f, const int *elements, const int *neighbors, const vec3_t projectorigin, const vec3_t projectdirection, float projectdistance, int nummarktris, const int *marktris, vec3_t trismins, vec3_t trismaxs)
1290 {
1291         int i, tris, outverts;
1292         if (projectdistance < 0.1)
1293         {
1294                 Con_Printf("R_Shadow_Volume: projectdistance %f\n", projectdistance);
1295                 return;
1296         }
1297         if (!numverts || !nummarktris)
1298                 return;
1299         // make sure shadowelements is big enough for this volume
1300         if (maxshadowtriangles < nummarktris*8 || maxshadowvertices < numverts*2)
1301                 R_Shadow_ResizeShadowArrays(numverts, nummarktris, 2, 8);
1302
1303         if (maxvertexupdate < numverts)
1304         {
1305                 maxvertexupdate = numverts;
1306                 if (vertexupdate)
1307                         Mem_Free(vertexupdate);
1308                 if (vertexremap)
1309                         Mem_Free(vertexremap);
1310                 vertexupdate = (int *)Mem_Alloc(r_main_mempool, maxvertexupdate * sizeof(int));
1311                 vertexremap = (int *)Mem_Alloc(r_main_mempool, maxvertexupdate * sizeof(int));
1312                 vertexupdatenum = 0;
1313         }
1314         vertexupdatenum++;
1315         if (vertexupdatenum == 0)
1316         {
1317                 vertexupdatenum = 1;
1318                 memset(vertexupdate, 0, maxvertexupdate * sizeof(int));
1319                 memset(vertexremap, 0, maxvertexupdate * sizeof(int));
1320         }
1321
1322         for (i = 0;i < nummarktris;i++)
1323                 shadowmark[marktris[i]] = shadowmarkcount;
1324
1325         if (r_shadow_compilingrtlight)
1326         {
1327                 // if we're compiling an rtlight, capture the mesh
1328                 //tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1329                 //Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_zpass, NULL, NULL, NULL, shadowvertex3f, NULL, NULL, NULL, NULL, tris, shadowelements);
1330                 tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1331                 Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_zfail, NULL, NULL, NULL, shadowvertex3f, NULL, NULL, NULL, NULL, tris, shadowelements);
1332         }
1333         else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
1334         {
1335                 tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1336                 R_Mesh_PrepareVertices_Position_Arrays(outverts, shadowvertex3f);
1337                 R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
1338         }
1339         else
1340         {
1341                 // decide which type of shadow to generate and set stencil mode
1342                 R_Shadow_RenderMode_StencilShadowVolumes(R_Shadow_UseZPass(trismins, trismaxs));
1343                 // generate the sides or a solid volume, depending on type
1344                 if (r_shadow_rendermode >= R_SHADOW_RENDERMODE_ZPASS_STENCIL && r_shadow_rendermode <= R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE)
1345                         tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1346                 else
1347                         tris = R_Shadow_ConstructShadowVolume_ZFail(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
1348                 r_refdef.stats.lights_dynamicshadowtriangles += tris;
1349                 r_refdef.stats.lights_shadowtriangles += tris;
1350                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
1351                 {
1352                         // increment stencil if frontface is infront of depthbuffer
1353                         GL_CullFace(r_refdef.view.cullface_front);
1354                         R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_DECR, GL_ALWAYS, 128, 255);
1355                         R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
1356                         // decrement stencil if backface is infront of depthbuffer
1357                         GL_CullFace(r_refdef.view.cullface_back);
1358                         R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_INCR, GL_ALWAYS, 128, 255);
1359                 }
1360                 else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCIL)
1361                 {
1362                         // decrement stencil if backface is behind depthbuffer
1363                         GL_CullFace(r_refdef.view.cullface_front);
1364                         R_SetStencil(true, 255, GL_KEEP, GL_DECR, GL_KEEP, GL_ALWAYS, 128, 255);
1365                         R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
1366                         // increment stencil if frontface is behind depthbuffer
1367                         GL_CullFace(r_refdef.view.cullface_back);
1368                         R_SetStencil(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_ALWAYS, 128, 255);
1369                 }
1370                 R_Mesh_PrepareVertices_Position_Arrays(outverts, shadowvertex3f);
1371                 R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, NULL, NULL, 0);
1372         }
1373 }
1374
1375 int R_Shadow_CalcTriangleSideMask(const vec3_t p1, const vec3_t p2, const vec3_t p3, float bias)
1376 {
1377     // p1, p2, p3 are in the cubemap's local coordinate system
1378     // bias = border/(size - border)
1379         int mask = 0x3F;
1380
1381     float dp1 = p1[0] + p1[1], dn1 = p1[0] - p1[1], ap1 = fabs(dp1), an1 = fabs(dn1),
1382           dp2 = p2[0] + p2[1], dn2 = p2[0] - p2[1], ap2 = fabs(dp2), an2 = fabs(dn2),
1383           dp3 = p3[0] + p3[1], dn3 = p3[0] - p3[1], ap3 = fabs(dp3), an3 = fabs(dn3);
1384         if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1385         mask &= (3<<4)
1386                         | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1387                         | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1388                         | (dp3 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1389     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1390         mask &= (3<<4)
1391             | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
1392             | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))            
1393             | (dn3 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1394
1395     dp1 = p1[1] + p1[2], dn1 = p1[1] - p1[2], ap1 = fabs(dp1), an1 = fabs(dn1),
1396     dp2 = p2[1] + p2[2], dn2 = p2[1] - p2[2], ap2 = fabs(dp2), an2 = fabs(dn2),
1397     dp3 = p3[1] + p3[2], dn3 = p3[1] - p3[2], ap3 = fabs(dp3), an3 = fabs(dn3);
1398     if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1399         mask &= (3<<0)
1400             | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
1401             | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))            
1402             | (dp3 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1403     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1404         mask &= (3<<0)
1405             | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1406             | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1407             | (dn3 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1408
1409     dp1 = p1[2] + p1[0], dn1 = p1[2] - p1[0], ap1 = fabs(dp1), an1 = fabs(dn1),
1410     dp2 = p2[2] + p2[0], dn2 = p2[2] - p2[0], ap2 = fabs(dp2), an2 = fabs(dn2),
1411     dp3 = p3[2] + p3[0], dn3 = p3[2] - p3[0], ap3 = fabs(dp3), an3 = fabs(dn3);
1412     if(ap1 > bias*an1 && ap2 > bias*an2 && ap3 > bias*an3)
1413         mask &= (3<<2)
1414             | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1415             | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1416             | (dp3 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1417     if(an1 > bias*ap1 && an2 > bias*ap2 && an3 > bias*ap3)
1418         mask &= (3<<2)
1419             | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1420             | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1421             | (dn3 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1422
1423         return mask;
1424 }
1425
1426 int R_Shadow_CalcBBoxSideMask(const vec3_t mins, const vec3_t maxs, const matrix4x4_t *worldtolight, const matrix4x4_t *radiustolight, float bias)
1427 {
1428         vec3_t center, radius, lightcenter, lightradius, pmin, pmax;
1429         float dp1, dn1, ap1, an1, dp2, dn2, ap2, an2;
1430         int mask = 0x3F;
1431
1432         VectorSubtract(maxs, mins, radius);
1433     VectorScale(radius, 0.5f, radius);
1434     VectorAdd(mins, radius, center);
1435     Matrix4x4_Transform(worldtolight, center, lightcenter);
1436         Matrix4x4_Transform3x3(radiustolight, radius, lightradius);
1437         VectorSubtract(lightcenter, lightradius, pmin);
1438         VectorAdd(lightcenter, lightradius, pmax);
1439
1440     dp1 = pmax[0] + pmax[1], dn1 = pmax[0] - pmin[1], ap1 = fabs(dp1), an1 = fabs(dn1),
1441     dp2 = pmin[0] + pmin[1], dn2 = pmin[0] - pmax[1], ap2 = fabs(dp2), an2 = fabs(dn2);
1442     if(ap1 > bias*an1 && ap2 > bias*an2)
1443         mask &= (3<<4)
1444             | (dp1 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2))
1445             | (dp2 >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1446     if(an1 > bias*ap1 && an2 > bias*ap2)
1447         mask &= (3<<4)
1448             | (dn1 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2))
1449             | (dn2 >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1450
1451     dp1 = pmax[1] + pmax[2], dn1 = pmax[1] - pmin[2], ap1 = fabs(dp1), an1 = fabs(dn1),
1452     dp2 = pmin[1] + pmin[2], dn2 = pmin[1] - pmax[2], ap2 = fabs(dp2), an2 = fabs(dn2);
1453     if(ap1 > bias*an1 && ap2 > bias*an2)
1454         mask &= (3<<0)
1455             | (dp1 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4))
1456             | (dp2 >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1457     if(an1 > bias*ap1 && an2 > bias*ap2)
1458         mask &= (3<<0)
1459             | (dn1 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4))
1460             | (dn2 >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1461
1462     dp1 = pmax[2] + pmax[0], dn1 = pmax[2] - pmin[0], ap1 = fabs(dp1), an1 = fabs(dn1),
1463     dp2 = pmin[2] + pmin[0], dn2 = pmin[2] - pmax[0], ap2 = fabs(dp2), an2 = fabs(dn2);
1464     if(ap1 > bias*an1 && ap2 > bias*an2)
1465         mask &= (3<<2)
1466             | (dp1 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0))
1467             | (dp2 >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1468     if(an1 > bias*ap1 && an2 > bias*ap2)
1469         mask &= (3<<2)
1470             | (dn1 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0))
1471             | (dn2 >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1472
1473     return mask;
1474 }
1475
1476 #define R_Shadow_CalcEntitySideMask(ent, worldtolight, radiustolight, bias) R_Shadow_CalcBBoxSideMask((ent)->mins, (ent)->maxs, worldtolight, radiustolight, bias)
1477
1478 int R_Shadow_CalcSphereSideMask(const vec3_t p, float radius, float bias)
1479 {
1480     // p is in the cubemap's local coordinate system
1481     // bias = border/(size - border)
1482     float dxyp = p[0] + p[1], dxyn = p[0] - p[1], axyp = fabs(dxyp), axyn = fabs(dxyn);
1483     float dyzp = p[1] + p[2], dyzn = p[1] - p[2], ayzp = fabs(dyzp), ayzn = fabs(dyzn);
1484     float dzxp = p[2] + p[0], dzxn = p[2] - p[0], azxp = fabs(dzxp), azxn = fabs(dzxn);
1485     int mask = 0x3F;
1486     if(axyp > bias*axyn + radius) mask &= dxyp < 0 ? ~((1<<0)|(1<<2)) : ~((2<<0)|(2<<2));
1487     if(axyn > bias*axyp + radius) mask &= dxyn < 0 ? ~((1<<0)|(2<<2)) : ~((2<<0)|(1<<2));
1488     if(ayzp > bias*ayzn + radius) mask &= dyzp < 0 ? ~((1<<2)|(1<<4)) : ~((2<<2)|(2<<4));
1489     if(ayzn > bias*ayzp + radius) mask &= dyzn < 0 ? ~((1<<2)|(2<<4)) : ~((2<<2)|(1<<4));
1490     if(azxp > bias*azxn + radius) mask &= dzxp < 0 ? ~((1<<4)|(1<<0)) : ~((2<<4)|(2<<0));
1491     if(azxn > bias*azxp + radius) mask &= dzxn < 0 ? ~((1<<4)|(2<<0)) : ~((2<<4)|(1<<0));
1492     return mask;
1493 }
1494
1495 int R_Shadow_CullFrustumSides(rtlight_t *rtlight, float size, float border)
1496 {
1497         int i;
1498         vec3_t p, n;
1499         int sides = 0x3F, masks[6] = { 3<<4, 3<<4, 3<<0, 3<<0, 3<<2, 3<<2 };
1500         float scale = (size - 2*border)/size, len;
1501         float bias = border / (float)(size - border), dp, dn, ap, an;
1502         // check if cone enclosing side would cross frustum plane 
1503         scale = 2 / (scale*scale + 2);
1504         for (i = 0;i < 5;i++)
1505         {
1506                 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) > -0.03125)
1507                         continue;
1508                 Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[i].normal, n);
1509                 len = scale*VectorLength2(n);
1510                 if(n[0]*n[0] > len) sides &= n[0] < 0 ? ~(1<<0) : ~(2 << 0);
1511                 if(n[1]*n[1] > len) sides &= n[1] < 0 ? ~(1<<2) : ~(2 << 2);
1512                 if(n[2]*n[2] > len) sides &= n[2] < 0 ? ~(1<<4) : ~(2 << 4);
1513         }
1514         if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[4]) >= r_refdef.farclip - r_refdef.nearclip + 0.03125)
1515         {
1516         Matrix4x4_Transform3x3(&rtlight->matrix_worldtolight, r_refdef.view.frustum[4].normal, n);
1517         len = scale*VectorLength(n);
1518                 if(n[0]*n[0] > len) sides &= n[0] >= 0 ? ~(1<<0) : ~(2 << 0);
1519                 if(n[1]*n[1] > len) sides &= n[1] >= 0 ? ~(1<<2) : ~(2 << 2);
1520                 if(n[2]*n[2] > len) sides &= n[2] >= 0 ? ~(1<<4) : ~(2 << 4);
1521         }
1522         // this next test usually clips off more sides than the former, but occasionally clips fewer/different ones, so do both and combine results
1523         // check if frustum corners/origin cross plane sides
1524 #if 1
1525     // infinite version, assumes frustum corners merely give direction and extend to infinite distance
1526     Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.origin, p);
1527     dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
1528     masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1529     masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1530     dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
1531     masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1532     masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1533     dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
1534     masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1535     masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1536     for (i = 0;i < 4;i++)
1537     {
1538         Matrix4x4_Transform(&rtlight->matrix_worldtolight, r_refdef.view.frustumcorner[i], n);
1539         VectorSubtract(n, p, n);
1540         dp = n[0] + n[1], dn = n[0] - n[1], ap = fabs(dp), an = fabs(dn);
1541         if(ap > 0) masks[0] |= dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2);
1542         if(an > 0) masks[1] |= dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2);
1543         dp = n[1] + n[2], dn = n[1] - n[2], ap = fabs(dp), an = fabs(dn);
1544         if(ap > 0) masks[2] |= dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4);
1545         if(an > 0) masks[3] |= dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4);
1546         dp = n[2] + n[0], dn = n[2] - n[0], ap = fabs(dp), an = fabs(dn);
1547         if(ap > 0) masks[4] |= dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0);
1548         if(an > 0) masks[5] |= dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0);
1549     }
1550 #else
1551     // finite version, assumes corners are a finite distance from origin dependent on far plane
1552         for (i = 0;i < 5;i++)
1553         {
1554                 Matrix4x4_Transform(&rtlight->matrix_worldtolight, !i ? r_refdef.view.origin : r_refdef.view.frustumcorner[i-1], p);
1555                 dp = p[0] + p[1], dn = p[0] - p[1], ap = fabs(dp), an = fabs(dn);
1556                 masks[0] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<0)|(1<<2) : (2<<0)|(2<<2));
1557                 masks[1] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<0)|(2<<2) : (2<<0)|(1<<2));
1558                 dp = p[1] + p[2], dn = p[1] - p[2], ap = fabs(dp), an = fabs(dn);
1559                 masks[2] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<2)|(1<<4) : (2<<2)|(2<<4));
1560                 masks[3] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<2)|(2<<4) : (2<<2)|(1<<4));
1561                 dp = p[2] + p[0], dn = p[2] - p[0], ap = fabs(dp), an = fabs(dn);
1562                 masks[4] |= ap <= bias*an ? 0x3F : (dp >= 0 ? (1<<4)|(1<<0) : (2<<4)|(2<<0));
1563                 masks[5] |= an <= bias*ap ? 0x3F : (dn >= 0 ? (1<<4)|(2<<0) : (2<<4)|(1<<0));
1564         }
1565 #endif
1566         return sides & masks[0] & masks[1] & masks[2] & masks[3] & masks[4] & masks[5];
1567 }
1568
1569 int R_Shadow_ChooseSidesFromBox(int firsttriangle, int numtris, const float *invertex3f, const int *elements, const matrix4x4_t *worldtolight, const vec3_t projectorigin, const vec3_t projectdirection, const vec3_t lightmins, const vec3_t lightmaxs, const vec3_t surfacemins, const vec3_t surfacemaxs, int *totals)
1570 {
1571         int t, tend;
1572         const int *e;
1573         const float *v[3];
1574         float normal[3];
1575         vec3_t p[3];
1576         float bias;
1577         int mask, surfacemask = 0;
1578         if (!BoxesOverlap(lightmins, lightmaxs, surfacemins, surfacemaxs))
1579                 return 0;
1580         bias = r_shadow_shadowmapborder / (float)(r_shadow_shadowmapmaxsize - r_shadow_shadowmapborder);
1581         tend = firsttriangle + numtris;
1582         if (BoxInsideBox(surfacemins, surfacemaxs, lightmins, lightmaxs))
1583         {
1584                 // surface box entirely inside light box, no box cull
1585                 if (projectdirection)
1586                 {
1587                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1588                         {
1589                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1590                                 TriangleNormal(v[0], v[1], v[2], normal);
1591                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0))
1592                                 {
1593                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1594                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1595                                         surfacemask |= mask;
1596                                         if(totals)
1597                                         {
1598                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1599                                                 shadowsides[numshadowsides] = mask;
1600                                                 shadowsideslist[numshadowsides++] = t;
1601                                         }
1602                                 }
1603                         }
1604                 }
1605                 else
1606                 {
1607                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1608                         {
1609                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1610                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2]))
1611                                 {
1612                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1613                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1614                                         surfacemask |= mask;
1615                                         if(totals)
1616                                         {
1617                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1618                                                 shadowsides[numshadowsides] = mask;
1619                                                 shadowsideslist[numshadowsides++] = t;
1620                                         }
1621                                 }
1622                         }
1623                 }
1624         }
1625         else
1626         {
1627                 // surface box not entirely inside light box, cull each triangle
1628                 if (projectdirection)
1629                 {
1630                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1631                         {
1632                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3,     v[2] = invertex3f + e[2] * 3;
1633                                 TriangleNormal(v[0], v[1], v[2], normal);
1634                                 if (r_shadow_frontsidecasting.integer == (DotProduct(normal, projectdirection) < 0)
1635                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1636                                 {
1637                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1638                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1639                                         surfacemask |= mask;
1640                                         if(totals)
1641                                         {
1642                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1643                                                 shadowsides[numshadowsides] = mask;
1644                                                 shadowsideslist[numshadowsides++] = t;
1645                                         }
1646                                 }
1647                         }
1648                 }
1649                 else
1650                 {
1651                         for (t = firsttriangle, e = elements + t * 3;t < tend;t++, e += 3)
1652                         {
1653                                 v[0] = invertex3f + e[0] * 3, v[1] = invertex3f + e[1] * 3, v[2] = invertex3f + e[2] * 3;
1654                                 if (r_shadow_frontsidecasting.integer == PointInfrontOfTriangle(projectorigin, v[0], v[1], v[2])
1655                                  && TriangleOverlapsBox(v[0], v[1], v[2], lightmins, lightmaxs))
1656                                 {
1657                                         Matrix4x4_Transform(worldtolight, v[0], p[0]), Matrix4x4_Transform(worldtolight, v[1], p[1]), Matrix4x4_Transform(worldtolight, v[2], p[2]);
1658                                         mask = R_Shadow_CalcTriangleSideMask(p[0], p[1], p[2], bias);
1659                                         surfacemask |= mask;
1660                                         if(totals)
1661                                         {
1662                                                 totals[0] += mask&1, totals[1] += (mask>>1)&1, totals[2] += (mask>>2)&1, totals[3] += (mask>>3)&1, totals[4] += (mask>>4)&1, totals[5] += mask>>5;
1663                                                 shadowsides[numshadowsides] = mask;
1664                                                 shadowsideslist[numshadowsides++] = t;
1665                                         }
1666                                 }
1667                         }
1668                 }
1669         }
1670         return surfacemask;
1671 }
1672
1673 void R_Shadow_ShadowMapFromList(int numverts, int numtris, const float *vertex3f, const int *elements, int numsidetris, const int *sidetotals, const unsigned char *sides, const int *sidetris)
1674 {
1675         int i, j, outtriangles = 0;
1676         int *outelement3i[6];
1677         if (!numverts || !numsidetris || !r_shadow_compilingrtlight)
1678                 return;
1679         outtriangles = sidetotals[0] + sidetotals[1] + sidetotals[2] + sidetotals[3] + sidetotals[4] + sidetotals[5];
1680         // make sure shadowelements is big enough for this mesh
1681         if (maxshadowtriangles < outtriangles)
1682                 R_Shadow_ResizeShadowArrays(0, outtriangles, 0, 1);
1683
1684         // compute the offset and size of the separate index lists for each cubemap side
1685         outtriangles = 0;
1686         for (i = 0;i < 6;i++)
1687         {
1688                 outelement3i[i] = shadowelements + outtriangles * 3;
1689                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sideoffsets[i] = outtriangles;
1690                 r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap->sidetotals[i] = sidetotals[i];
1691                 outtriangles += sidetotals[i];
1692         }
1693
1694         // gather up the (sparse) triangles into separate index lists for each cubemap side
1695         for (i = 0;i < numsidetris;i++)
1696         {
1697                 const int *element = elements + sidetris[i] * 3;
1698                 for (j = 0;j < 6;j++)
1699                 {
1700                         if (sides[i] & (1 << j))
1701                         {
1702                                 outelement3i[j][0] = element[0];
1703                                 outelement3i[j][1] = element[1];
1704                                 outelement3i[j][2] = element[2];
1705                                 outelement3i[j] += 3;
1706                         }
1707                 }
1708         }
1709                         
1710         Mod_ShadowMesh_AddMesh(r_main_mempool, r_shadow_compilingrtlight->static_meshchain_shadow_shadowmap, NULL, NULL, NULL, vertex3f, NULL, NULL, NULL, NULL, outtriangles, shadowelements);
1711 }
1712
1713 static void R_Shadow_MakeTextures_MakeCorona(void)
1714 {
1715         float dx, dy;
1716         int x, y, a;
1717         unsigned char pixels[32][32][4];
1718         for (y = 0;y < 32;y++)
1719         {
1720                 dy = (y - 15.5f) * (1.0f / 16.0f);
1721                 for (x = 0;x < 32;x++)
1722                 {
1723                         dx = (x - 15.5f) * (1.0f / 16.0f);
1724                         a = (int)(((1.0f / (dx * dx + dy * dy + 0.2f)) - (1.0f / (1.0f + 0.2))) * 32.0f / (1.0f / (1.0f + 0.2)));
1725                         a = bound(0, a, 255);
1726                         pixels[y][x][0] = a;
1727                         pixels[y][x][1] = a;
1728                         pixels[y][x][2] = a;
1729                         pixels[y][x][3] = 255;
1730                 }
1731         }
1732         r_shadow_lightcorona = R_SkinFrame_LoadInternalBGRA("lightcorona", TEXF_FORCELINEAR, &pixels[0][0][0], 32, 32);
1733 }
1734
1735 static unsigned int R_Shadow_MakeTextures_SamplePoint(float x, float y, float z)
1736 {
1737         float dist = sqrt(x*x+y*y+z*z);
1738         float intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1739         // note this code could suffer byte order issues except that it is multiplying by an integer that reads the same both ways
1740         return (unsigned char)bound(0, intensity * 256.0f, 255) * 0x01010101;
1741 }
1742
1743 static void R_Shadow_MakeTextures(void)
1744 {
1745         int x, y, z;
1746         float intensity, dist;
1747         unsigned int *data;
1748         R_Shadow_FreeShadowMaps();
1749         R_FreeTexturePool(&r_shadow_texturepool);
1750         r_shadow_texturepool = R_AllocTexturePool();
1751         r_shadow_attenlinearscale = r_shadow_lightattenuationlinearscale.value;
1752         r_shadow_attendividebias = r_shadow_lightattenuationdividebias.value;
1753         data = (unsigned int *)Mem_Alloc(tempmempool, max(max(ATTEN3DSIZE*ATTEN3DSIZE*ATTEN3DSIZE, ATTEN2DSIZE*ATTEN2DSIZE), ATTEN1DSIZE) * 4);
1754         // the table includes one additional value to avoid the need to clamp indexing due to minor math errors
1755         for (x = 0;x <= ATTENTABLESIZE;x++)
1756         {
1757                 dist = (x + 0.5f) * (1.0f / ATTENTABLESIZE) * (1.0f / 0.9375);
1758                 intensity = dist < 1 ? ((1.0f - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist)) : 0;
1759                 r_shadow_attentable[x] = bound(0, intensity, 1);
1760         }
1761         // 1D gradient texture
1762         for (x = 0;x < ATTEN1DSIZE;x++)
1763                 data[x] = R_Shadow_MakeTextures_SamplePoint((x + 0.5f) * (1.0f / ATTEN1DSIZE) * (1.0f / 0.9375), 0, 0);
1764         r_shadow_attenuationgradienttexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation1d", ATTEN1DSIZE, 1, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, -1, NULL);
1765         // 2D circle texture
1766         for (y = 0;y < ATTEN2DSIZE;y++)
1767                 for (x = 0;x < ATTEN2DSIZE;x++)
1768                         data[y*ATTEN2DSIZE+x] = R_Shadow_MakeTextures_SamplePoint(((x + 0.5f) * (2.0f / ATTEN2DSIZE) - 1.0f) * (1.0f / 0.9375), ((y + 0.5f) * (2.0f / ATTEN2DSIZE) - 1.0f) * (1.0f / 0.9375), 0);
1769         r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", ATTEN2DSIZE, ATTEN2DSIZE, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, -1, NULL);
1770         // 3D sphere texture
1771         if (r_shadow_texture3d.integer && vid.support.ext_texture_3d)
1772         {
1773                 for (z = 0;z < ATTEN3DSIZE;z++)
1774                         for (y = 0;y < ATTEN3DSIZE;y++)
1775                                 for (x = 0;x < ATTEN3DSIZE;x++)
1776                                         data[(z*ATTEN3DSIZE+y)*ATTEN3DSIZE+x] = R_Shadow_MakeTextures_SamplePoint(((x + 0.5f) * (2.0f / ATTEN3DSIZE) - 1.0f) * (1.0f / 0.9375), ((y + 0.5f) * (2.0f / ATTEN3DSIZE) - 1.0f) * (1.0f / 0.9375), ((z + 0.5f) * (2.0f / ATTEN3DSIZE) - 1.0f) * (1.0f / 0.9375));
1777                 r_shadow_attenuation3dtexture = R_LoadTexture3D(r_shadow_texturepool, "attenuation3d", ATTEN3DSIZE, ATTEN3DSIZE, ATTEN3DSIZE, (unsigned char *)data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, -1, NULL);
1778         }
1779         else
1780                 r_shadow_attenuation3dtexture = NULL;
1781         Mem_Free(data);
1782
1783         R_Shadow_MakeTextures_MakeCorona();
1784
1785         // Editor light sprites
1786         r_editlights_sprcursor = R_SkinFrame_LoadInternal8bit("gfx/editlights/cursor", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1787         "................"
1788         ".3............3."
1789         "..5...2332...5.."
1790         "...7.3....3.7..."
1791         "....7......7...."
1792         "...3.7....7.3..."
1793         "..2...7..7...2.."
1794         "..3..........3.."
1795         "..3..........3.."
1796         "..2...7..7...2.."
1797         "...3.7....7.3..."
1798         "....7......7...."
1799         "...7.3....3.7..."
1800         "..5...2332...5.."
1801         ".3............3."
1802         "................"
1803         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1804         r_editlights_sprlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/light", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1805         "................"
1806         "................"
1807         "......1111......"
1808         "....11233211...."
1809         "...1234554321..."
1810         "...1356776531..."
1811         "..124677776421.."
1812         "..135777777531.."
1813         "..135777777531.."
1814         "..124677776421.."
1815         "...1356776531..."
1816         "...1234554321..."
1817         "....11233211...."
1818         "......1111......"
1819         "................"
1820         "................"
1821         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1822         r_editlights_sprnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/noshadow", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1823         "................"
1824         "................"
1825         "......1111......"
1826         "....11233211...."
1827         "...1234554321..."
1828         "...1356226531..."
1829         "..12462..26421.."
1830         "..1352....2531.."
1831         "..1352....2531.."
1832         "..12462..26421.."
1833         "...1356226531..."
1834         "...1234554321..."
1835         "....11233211...."
1836         "......1111......"
1837         "................"
1838         "................"
1839         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1840         r_editlights_sprcubemaplight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemaplight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1841         "................"
1842         "................"
1843         "......2772......"
1844         "....27755772...."
1845         "..277533335772.."
1846         "..753333333357.."
1847         "..777533335777.."
1848         "..735775577537.."
1849         "..733357753337.."
1850         "..733337733337.."
1851         "..753337733357.."
1852         "..277537735772.."
1853         "....27777772...."
1854         "......2772......"
1855         "................"
1856         "................"
1857         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1858         r_editlights_sprcubemapnoshadowlight = R_SkinFrame_LoadInternal8bit("gfx/editlights/cubemapnoshadowlight", TEXF_ALPHA | TEXF_CLAMP, (const unsigned char *)
1859         "................"
1860         "................"
1861         "......2772......"
1862         "....27722772...."
1863         "..2772....2772.."
1864         "..72........27.."
1865         "..7772....2777.."
1866         "..7.27722772.7.."
1867         "..7...2772...7.."
1868         "..7....77....7.."
1869         "..72...77...27.."
1870         "..2772.77.2772.."
1871         "....27777772...."
1872         "......2772......"
1873         "................"
1874         "................"
1875         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1876         r_editlights_sprselection = R_SkinFrame_LoadInternal8bit("gfx/editlights/selection", TEXF_ALPHA | TEXF_CLAMP, (unsigned char *)
1877         "................"
1878         ".777752..257777."
1879         ".742........247."
1880         ".72..........27."
1881         ".7............7."
1882         ".5............5."
1883         ".2............2."
1884         "................"
1885         "................"
1886         ".2............2."
1887         ".5............5."
1888         ".7............7."
1889         ".72..........27."
1890         ".742........247."
1891         ".777752..257777."
1892         "................"
1893         , 16, 16, palette_bgra_embeddedpic, palette_bgra_embeddedpic);
1894 }
1895
1896 void R_Shadow_ValidateCvars(void)
1897 {
1898         if (r_shadow_texture3d.integer && !vid.support.ext_texture_3d)
1899                 Cvar_SetValueQuick(&r_shadow_texture3d, 0);
1900         if (gl_ext_separatestencil.integer && !vid.support.ati_separate_stencil)
1901                 Cvar_SetValueQuick(&gl_ext_separatestencil, 0);
1902         if (gl_ext_stenciltwoside.integer && !vid.support.ext_stencil_two_side)
1903                 Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0);
1904 }
1905
1906 //static const r_vertexposition_t resetvertexposition[3] = {{0, 0, 0}};
1907
1908 void R_Shadow_RenderMode_Begin(void)
1909 {
1910 #if 0
1911         GLint drawbuffer;
1912         GLint readbuffer;
1913 #endif
1914         R_Shadow_ValidateCvars();
1915
1916         if (!r_shadow_attenuation2dtexture
1917          || (!r_shadow_attenuation3dtexture && r_shadow_texture3d.integer)
1918          || r_shadow_lightattenuationdividebias.value != r_shadow_attendividebias
1919          || r_shadow_lightattenuationlinearscale.value != r_shadow_attenlinearscale)
1920                 R_Shadow_MakeTextures();
1921
1922         CHECKGLERROR
1923         R_Mesh_ResetTextureState();
1924 //      R_Mesh_PrepareVertices_Position(0, resetvertexposition, NULL);
1925         GL_BlendFunc(GL_ONE, GL_ZERO);
1926         GL_DepthRange(0, 1);
1927         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
1928         GL_DepthTest(true);
1929         GL_DepthMask(false);
1930         GL_Color(0, 0, 0, 1);
1931         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
1932
1933         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
1934
1935         if (gl_ext_separatestencil.integer && vid.support.ati_separate_stencil)
1936         {
1937                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL;
1938                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL;
1939         }
1940         else if (gl_ext_stenciltwoside.integer && vid.support.ext_stencil_two_side)
1941         {
1942                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE;
1943                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE;
1944         }
1945         else
1946         {
1947                 r_shadow_shadowingrendermode_zpass = R_SHADOW_RENDERMODE_ZPASS_STENCIL;
1948                 r_shadow_shadowingrendermode_zfail = R_SHADOW_RENDERMODE_ZFAIL_STENCIL;
1949         }
1950
1951         switch(vid.renderpath)
1952         {
1953         case RENDERPATH_GL20:
1954         case RENDERPATH_CGGL:
1955         case RENDERPATH_D3D9:
1956         case RENDERPATH_D3D10:
1957         case RENDERPATH_D3D11:
1958                 r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_GLSL;
1959                 break;
1960         case RENDERPATH_GL13:
1961         case RENDERPATH_GL11:
1962                 if (r_textureunits.integer >= 2 && vid.texunits >= 2 && r_shadow_texture3d.integer && r_shadow_attenuation3dtexture)
1963                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN;
1964                 else if (r_textureunits.integer >= 3 && vid.texunits >= 3)
1965                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN;
1966                 else if (r_textureunits.integer >= 2 && vid.texunits >= 2)
1967                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN;
1968                 else
1969                         r_shadow_lightingrendermode = R_SHADOW_RENDERMODE_LIGHT_VERTEX;
1970                 break;
1971         }
1972
1973         CHECKGLERROR
1974 #if 0
1975         qglGetIntegerv(GL_DRAW_BUFFER, &drawbuffer);CHECKGLERROR
1976         qglGetIntegerv(GL_READ_BUFFER, &readbuffer);CHECKGLERROR
1977         r_shadow_drawbuffer = drawbuffer;
1978         r_shadow_readbuffer = readbuffer;
1979 #endif
1980         r_shadow_cullface_front = r_refdef.view.cullface_front;
1981         r_shadow_cullface_back = r_refdef.view.cullface_back;
1982 }
1983
1984 void R_Shadow_RenderMode_ActiveLight(const rtlight_t *rtlight)
1985 {
1986         rsurface.rtlight = rtlight;
1987 }
1988
1989 void R_Shadow_RenderMode_Reset(void)
1990 {
1991         R_Mesh_ResetRenderTargets();
1992         R_SetViewport(&r_refdef.view.viewport);
1993         GL_Scissor(r_shadow_lightscissor[0], r_shadow_lightscissor[1], r_shadow_lightscissor[2], r_shadow_lightscissor[3]);
1994         R_Mesh_ResetTextureState();
1995 //      R_Mesh_PrepareVertices_Position(0, resetvertexposition, NULL);
1996         GL_DepthRange(0, 1);
1997         GL_DepthTest(true);
1998         GL_DepthMask(false);
1999         GL_DepthFunc(GL_LEQUAL);
2000         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
2001         r_refdef.view.cullface_front = r_shadow_cullface_front;
2002         r_refdef.view.cullface_back = r_shadow_cullface_back;
2003         GL_CullFace(r_refdef.view.cullface_back);
2004         GL_Color(1, 1, 1, 1);
2005         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2006         GL_BlendFunc(GL_ONE, GL_ZERO);
2007         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
2008         r_shadow_usingshadowmaprect = false;
2009         r_shadow_usingshadowmapcube = false;
2010         r_shadow_usingshadowmap2d = false;
2011         r_shadow_usingshadowmaportho = false;
2012         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
2013 }
2014
2015 void R_Shadow_ClearStencil(void)
2016 {
2017         GL_Clear(GL_STENCIL_BUFFER_BIT, NULL, 1.0f, 128);
2018         r_refdef.stats.lights_clears++;
2019 }
2020
2021 void R_Shadow_RenderMode_StencilShadowVolumes(qboolean zpass)
2022 {
2023         r_shadow_rendermode_t mode = zpass ? r_shadow_shadowingrendermode_zpass : r_shadow_shadowingrendermode_zfail;
2024         if (r_shadow_rendermode == mode)
2025                 return;
2026         R_Shadow_RenderMode_Reset();
2027         GL_DepthFunc(GL_LESS);
2028         GL_ColorMask(0, 0, 0, 0);
2029         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
2030         GL_CullFace(GL_NONE);
2031         R_SetupShader_DepthOrShadow();
2032         r_shadow_rendermode = mode;
2033         switch(mode)
2034         {
2035         default:
2036                 break;
2037         case R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE:
2038         case R_SHADOW_RENDERMODE_ZPASS_SEPARATESTENCIL:
2039                 R_SetStencilSeparate(true, 255, GL_KEEP, GL_KEEP, GL_INCR, GL_KEEP, GL_KEEP, GL_DECR, GL_ALWAYS, GL_ALWAYS, 128, 255);
2040                 break;
2041         case R_SHADOW_RENDERMODE_ZFAIL_STENCILTWOSIDE:
2042         case R_SHADOW_RENDERMODE_ZFAIL_SEPARATESTENCIL:
2043                 R_SetStencilSeparate(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_KEEP, GL_DECR, GL_KEEP, GL_ALWAYS, GL_ALWAYS, 128, 255);
2044                 break;
2045         }
2046 }
2047
2048 static void R_Shadow_MakeVSDCT(void)
2049 {
2050         // maps to a 2x3 texture rectangle with normalized coordinates
2051         // +-
2052         // XX
2053         // YY
2054         // ZZ
2055         // stores abs(dir.xy), offset.xy/2.5
2056         unsigned char data[4*6] =
2057         {
2058                 255, 0, 0x33, 0x33, // +X: <1, 0>, <0.5, 0.5>
2059                 255, 0, 0x99, 0x33, // -X: <1, 0>, <1.5, 0.5>
2060                 0, 255, 0x33, 0x99, // +Y: <0, 1>, <0.5, 1.5>
2061                 0, 255, 0x99, 0x99, // -Y: <0, 1>, <1.5, 1.5>
2062                 0,   0, 0x33, 0xFF, // +Z: <0, 0>, <0.5, 2.5>
2063                 0,   0, 0x99, 0xFF, // -Z: <0, 0>, <1.5, 2.5>
2064         };
2065         r_shadow_shadowmapvsdcttexture = R_LoadTextureCubeMap(r_shadow_texturepool, "shadowmapvsdct", 1, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL);
2066 }
2067
2068 static void R_Shadow_MakeShadowMap(int side, int size)
2069 {
2070         switch (r_shadow_shadowmode)
2071         {
2072         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
2073                 if (r_shadow_shadowmap2dtexture) return;
2074                 r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2075                 r_shadow_shadowmap2dcolortexture = NULL;
2076                 switch(vid.renderpath)
2077                 {
2078 #ifdef SUPPORTD3D
2079                 case RENDERPATH_D3D9:
2080                         r_shadow_shadowmap2dcolortexture = R_LoadTexture2D(r_shadow_texturepool, "shadowmaprendertarget", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), NULL, TEXTYPE_BGRA, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALPHA, -1, NULL);
2081                         r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
2082                         break;
2083 #endif
2084                 default:
2085                         r_shadow_fbo2d = R_Mesh_CreateFramebufferObject(r_shadow_shadowmap2dtexture, NULL, NULL, NULL, NULL);
2086                         break;
2087                 }
2088                 break;
2089         case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
2090                 if (r_shadow_shadowmaprectangletexture) return;
2091                 r_shadow_shadowmaprectangletexture = R_LoadTextureShadowMapRectangle(r_shadow_texturepool, "shadowmap", size*2, size*3, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2092                 r_shadow_fborectangle = R_Mesh_CreateFramebufferObject(r_shadow_shadowmaprectangletexture, NULL, NULL, NULL, NULL);
2093                 break;
2094         case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
2095                 if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) return;
2096                 r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod] = R_LoadTextureShadowMapCube(r_shadow_texturepool, "shadowmapcube", size, r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
2097                 // special trick to get an empty fbo we configure ourselves...
2098                 r_shadow_fbocubeside[r_shadow_shadowmaplod] = R_Mesh_CreateFramebufferObject(NULL, NULL, NULL, NULL, NULL);
2099                 R_Mesh_SetRenderTargets(r_shadow_fbocubeside[r_shadow_shadowmaplod], NULL, NULL, NULL, NULL, NULL);
2100                 if (qglFramebufferTexture2DEXT)
2101                         qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
2102                 break;
2103         default:
2104                 return;
2105         }
2106
2107         // render depth into the fbo, do not render color at all
2108         // validate the fbo now
2109         if (qglDrawBuffer)
2110         {
2111                 int status;
2112                 qglDrawBuffer(GL_NONE);CHECKGLERROR
2113                 qglReadBuffer(GL_NONE);CHECKGLERROR
2114                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2115                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT && (r_shadow_shadowmapping.integer || r_shadow_deferred.integer))
2116                 {
2117                         Con_Printf("R_Shadow_MakeShadowMap: glCheckFramebufferStatusEXT returned %i\n", status);
2118                         Cvar_SetValueQuick(&r_shadow_shadowmapping, 0);
2119                         Cvar_SetValueQuick(&r_shadow_deferred, 0);
2120                 }
2121         }
2122 }
2123
2124 static float testcolor[4] = {0,1,0,1};
2125 void R_Shadow_RenderMode_ShadowMap(int side, int clear, int size)
2126 {
2127         float nearclip, farclip, bias;
2128         r_viewport_t viewport;
2129         int flipped;
2130         GLuint fbo = 0;
2131         nearclip = r_shadow_shadowmapping_nearclip.value / rsurface.rtlight->radius;
2132         farclip = 1.0f;
2133         bias = r_shadow_shadowmapping_bias.value * nearclip * (1024.0f / size);// * rsurface.rtlight->radius;
2134         r_shadow_shadowmap_parameters[1] = -nearclip * farclip / (farclip - nearclip) - 0.5f * bias;
2135         r_shadow_shadowmap_parameters[3] = 0.5f + 0.5f * (farclip + nearclip) / (farclip - nearclip);
2136         r_shadow_shadowmapside = side;
2137         r_shadow_shadowmapsize = size;
2138         switch (r_shadow_shadowmode)
2139         {
2140         case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
2141                 r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
2142                 r_shadow_shadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
2143                 R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
2144                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAP2D) goto init_done;
2145
2146                 // complex unrolled cube approach (more flexible)
2147                 if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
2148                         R_Shadow_MakeVSDCT();
2149                 if (!r_shadow_shadowmap2dtexture)
2150                         R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
2151                 if (r_shadow_shadowmap2dtexture) fbo = r_shadow_fbo2d;
2152                 r_shadow_shadowmap_texturescale[0] = 1.0f / R_TextureWidth(r_shadow_shadowmap2dtexture);
2153                 r_shadow_shadowmap_texturescale[1] = 1.0f / R_TextureHeight(r_shadow_shadowmap2dtexture);
2154                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAP2D;
2155                 break;
2156         case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
2157                 r_shadow_shadowmap_parameters[0] = 0.5f * (size - r_shadow_shadowmapborder);
2158                 r_shadow_shadowmap_parameters[2] = r_shadow_shadowmapvsdct ? 2.5f*size : size;
2159                 R_Viewport_InitRectSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, r_shadow_shadowmapborder, nearclip, farclip, NULL);
2160                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE) goto init_done;
2161
2162                 // complex unrolled cube approach (more flexible)
2163                 if (r_shadow_shadowmapvsdct && !r_shadow_shadowmapvsdcttexture)
2164                         R_Shadow_MakeVSDCT();
2165                 if (!r_shadow_shadowmaprectangletexture)
2166                         R_Shadow_MakeShadowMap(side, r_shadow_shadowmapmaxsize);
2167                 if(r_shadow_shadowmaprectangletexture) fbo = r_shadow_fborectangle;
2168                 r_shadow_shadowmap_texturescale[0] = 1.0f;
2169                 r_shadow_shadowmap_texturescale[1] = 1.0f;
2170                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE;
2171                 break;
2172         case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
2173                 r_shadow_shadowmap_parameters[0] = 1.0f;
2174                 r_shadow_shadowmap_parameters[2] = 1.0f;
2175                 R_Viewport_InitCubeSideView(&viewport, &rsurface.rtlight->matrix_lighttoworld, side, size, nearclip, farclip, NULL);
2176                 if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE) goto init_done;
2177
2178                 // simple cube approach
2179                 if (!r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod])
2180                         R_Shadow_MakeShadowMap(side, size);
2181                 if (r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]) fbo = r_shadow_fbocubeside[r_shadow_shadowmaplod];
2182                 r_shadow_shadowmap_texturescale[0] = 0.0f;
2183                 r_shadow_shadowmap_texturescale[1] = 0.0f;
2184                 r_shadow_rendermode = R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE;
2185                 break;
2186         default:
2187                 break;
2188         }
2189
2190         R_Shadow_RenderMode_Reset();
2191         if (fbo)
2192         {
2193                 R_Mesh_SetRenderTargets(fbo, r_shadow_shadowmap2dtexture, r_shadow_shadowmap2dcolortexture, NULL, NULL, NULL);
2194                 R_SetupShader_DepthOrShadow();
2195         }
2196         else
2197                 R_SetupShader_ShowDepth();
2198         GL_PolygonOffset(r_shadow_shadowmapping_polygonfactor.value, r_shadow_shadowmapping_polygonoffset.value);
2199         GL_DepthMask(true);
2200         GL_DepthTest(true);
2201
2202 init_done:
2203         R_SetViewport(&viewport);
2204         switch (r_shadow_rendermode)
2205         {
2206         case R_SHADOW_RENDERMODE_SHADOWMAP2D:
2207         case R_SHADOW_RENDERMODE_SHADOWMAPRECTANGLE:
2208                 flipped = (side & 1) ^ (side >> 2);
2209                 r_refdef.view.cullface_front = flipped ? r_shadow_cullface_back : r_shadow_cullface_front;
2210                 r_refdef.view.cullface_back = flipped ? r_shadow_cullface_front : r_shadow_cullface_back;
2211                 switch(vid.renderpath)
2212                 {
2213                 case RENDERPATH_GL11:
2214                 case RENDERPATH_GL13:
2215                 case RENDERPATH_GL20:
2216                 case RENDERPATH_CGGL:
2217                         GL_CullFace(r_refdef.view.cullface_back);
2218                         // OpenGL lets us scissor larger than the viewport, so go ahead and clear all views at once
2219                         if ((clear & ((2 << side) - 1)) == (1 << side)) // only clear if the side is the first in the mask
2220                         {
2221                                 // get tightest scissor rectangle that encloses all viewports in the clear mask
2222                                 int x1 = clear & 0x15 ? 0 : size;
2223                                 int x2 = clear & 0x2A ? 2 * size : size;
2224                                 int y1 = clear & 0x03 ? 0 : (clear & 0xC ? size : 2 * size);
2225                                 int y2 = clear & 0x30 ? 3 * size : (clear & 0xC ? 2 * size : size);
2226                                 GL_Scissor(x1, y1, x2 - x1, y2 - y1);
2227                                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
2228                         }
2229                         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2230                         break;
2231                 case RENDERPATH_D3D9:
2232                         // completely different meaning than in OpenGL path
2233                         r_shadow_shadowmap_parameters[1] = 0;
2234                         r_shadow_shadowmap_parameters[3] = -bias;
2235                         // we invert the cull mode because we flip the projection matrix
2236                         // NOTE: this actually does nothing because the DrawShadowMap code sets it to doublesided...
2237                         GL_CullFace(r_refdef.view.cullface_front);
2238                         // D3D considers it an error to use a scissor larger than the viewport...  clear just this view
2239                         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2240                         if (r_shadow_shadowmapsampler)
2241                         {
2242                                 GL_ColorMask(0,0,0,0);
2243                                 if (clear)
2244                                         GL_Clear(GL_DEPTH_BUFFER_BIT, testcolor, 1.0f, 0);
2245                         }
2246                         else
2247                         {
2248                                 GL_ColorMask(1,1,1,1);
2249                                 if (clear)
2250                                         GL_Clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT, testcolor, 1.0f, 0);
2251                         }
2252                         break;
2253                 case RENDERPATH_D3D10:
2254                 case RENDERPATH_D3D11:
2255                         // D3D considers it an error to use a scissor larger than the viewport...  clear just this view
2256                         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2257                         GL_ColorMask(0,0,0,0);
2258                         if (clear)
2259                                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
2260                         break;
2261                 }
2262                 break;
2263         case R_SHADOW_RENDERMODE_SHADOWMAPCUBESIDE:
2264                 if (qglFramebufferTexture2DEXT)
2265                         qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + side, R_GetTexture(r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]), 0);CHECKGLERROR
2266                 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
2267                 if (clear)
2268                         GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
2269                 break;
2270         default:
2271                 break;
2272         }
2273 }
2274
2275 void R_Shadow_RenderMode_Lighting(qboolean stenciltest, qboolean transparent, qboolean shadowmapping)
2276 {
2277         if (transparent)
2278         {
2279                 r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
2280                 r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
2281                 r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
2282                 r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
2283         }
2284         R_Shadow_RenderMode_Reset();
2285         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2286         if (!transparent)
2287                 GL_DepthFunc(GL_EQUAL);
2288         // do global setup needed for the chosen lighting mode
2289         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
2290                 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 0);
2291         if (shadowmapping)
2292         {
2293                 switch (r_shadow_shadowmode)
2294                 {
2295                 case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
2296                         r_shadow_usingshadowmap2d = true;
2297                         break;
2298                 case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
2299                         r_shadow_usingshadowmaprect = true;
2300                         break;
2301                 case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
2302                         r_shadow_usingshadowmapcube = true;
2303                         break;
2304                 default:
2305                         break;
2306                 }
2307         }
2308         r_shadow_rendermode = r_shadow_lightingrendermode;
2309         // only draw light where this geometry was already rendered AND the
2310         // stencil is 128 (values other than this mean shadow)
2311         if (stenciltest)
2312                 R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
2313         else
2314                 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
2315 }
2316
2317 static const unsigned short bboxelements[36] =
2318 {
2319         5, 1, 3, 5, 3, 7,
2320         6, 2, 0, 6, 0, 4,
2321         7, 3, 2, 7, 2, 6,
2322         4, 0, 1, 4, 1, 5,
2323         4, 5, 7, 4, 7, 6,
2324         1, 0, 2, 1, 2, 3,
2325 };
2326
2327 static const float bboxpoints[8][3] =
2328 {
2329         {-1,-1,-1},
2330         { 1,-1,-1},
2331         {-1, 1,-1},
2332         { 1, 1,-1},
2333         {-1,-1, 1},
2334         { 1,-1, 1},
2335         {-1, 1, 1},
2336         { 1, 1, 1},
2337 };
2338
2339 void R_Shadow_RenderMode_DrawDeferredLight(qboolean stenciltest, qboolean shadowmapping)
2340 {
2341         int i;
2342         float vertex3f[8*3];
2343         const matrix4x4_t *matrix = &rsurface.rtlight->matrix_lighttoworld;
2344 // do global setup needed for the chosen lighting mode
2345         R_Shadow_RenderMode_Reset();
2346         r_shadow_rendermode = r_shadow_lightingrendermode;
2347         R_EntityMatrix(&identitymatrix);
2348         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2349         // only draw light where this geometry was already rendered AND the
2350         // stencil is 128 (values other than this mean shadow)
2351         R_SetStencil(stenciltest, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
2352         R_Mesh_SetRenderTargets(r_shadow_prepasslightingfbo, r_shadow_prepassgeometrydepthtexture, r_shadow_prepasslightingdiffusetexture, r_shadow_prepasslightingspeculartexture, NULL, NULL);
2353
2354         if (shadowmapping)
2355         {
2356                 switch (r_shadow_shadowmode)
2357                 {
2358                 case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
2359                         r_shadow_usingshadowmap2d = true;
2360                         break;
2361                 case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
2362                         r_shadow_usingshadowmaprect = true;
2363                         break;
2364                 case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
2365                         r_shadow_usingshadowmapcube = true;
2366                         break;
2367                 default:
2368                         break;
2369                 }
2370         }
2371
2372         // render the lighting
2373         R_SetupShader_DeferredLight(rsurface.rtlight);
2374         for (i = 0;i < 8;i++)
2375                 Matrix4x4_Transform(matrix, bboxpoints[i], vertex3f + i*3);
2376         GL_ColorMask(1,1,1,1);
2377         GL_DepthMask(false);
2378         GL_DepthRange(0, 1);
2379         GL_PolygonOffset(0, 0);
2380         GL_DepthTest(true);
2381         GL_DepthFunc(GL_GREATER);
2382         GL_CullFace(r_refdef.view.cullface_back);
2383         R_Mesh_PrepareVertices_Position_Arrays(8, vertex3f);
2384         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
2385 }
2386
2387 void R_Shadow_RenderMode_VisibleShadowVolumes(void)
2388 {
2389         R_Shadow_RenderMode_Reset();
2390         GL_BlendFunc(GL_ONE, GL_ONE);
2391         GL_DepthRange(0, 1);
2392         GL_DepthTest(r_showshadowvolumes.integer < 2);
2393         GL_Color(0.0, 0.0125 * r_refdef.view.colorscale, 0.1 * r_refdef.view.colorscale, 1);
2394         GL_PolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
2395         GL_CullFace(GL_NONE);
2396         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLEVOLUMES;
2397 }
2398
2399 void R_Shadow_RenderMode_VisibleLighting(qboolean stenciltest, qboolean transparent)
2400 {
2401         R_Shadow_RenderMode_Reset();
2402         GL_BlendFunc(GL_ONE, GL_ONE);
2403         GL_DepthRange(0, 1);
2404         GL_DepthTest(r_showlighting.integer < 2);
2405         GL_Color(0.1 * r_refdef.view.colorscale, 0.0125 * r_refdef.view.colorscale, 0, 1);
2406         if (!transparent)
2407                 GL_DepthFunc(GL_EQUAL);
2408         R_SetStencil(stenciltest, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_EQUAL, 128, 255);
2409         r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING;
2410 }
2411
2412 void R_Shadow_RenderMode_End(void)
2413 {
2414         R_Shadow_RenderMode_Reset();
2415         R_Shadow_RenderMode_ActiveLight(NULL);
2416         GL_DepthMask(true);
2417         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
2418         r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
2419 }
2420
2421 int bboxedges[12][2] =
2422 {
2423         // top
2424         {0, 1}, // +X
2425         {0, 2}, // +Y
2426         {1, 3}, // Y, +X
2427         {2, 3}, // X, +Y
2428         // bottom
2429         {4, 5}, // +X
2430         {4, 6}, // +Y
2431         {5, 7}, // Y, +X
2432         {6, 7}, // X, +Y
2433         // verticals
2434         {0, 4}, // +Z
2435         {1, 5}, // X, +Z
2436         {2, 6}, // Y, +Z
2437         {3, 7}, // XY, +Z
2438 };
2439
2440 qboolean R_Shadow_ScissorForBBox(const float *mins, const float *maxs)
2441 {
2442         int i, ix1, iy1, ix2, iy2;
2443         float x1, y1, x2, y2;
2444         vec4_t v, v2;
2445         float vertex[20][3];
2446         int j, k;
2447         vec4_t plane4f;
2448         int numvertices;
2449         float corner[8][4];
2450         float dist[8];
2451         int sign[8];
2452         float f;
2453
2454         r_shadow_lightscissor[0] = r_refdef.view.viewport.x;
2455         r_shadow_lightscissor[1] = r_refdef.view.viewport.y;
2456         r_shadow_lightscissor[2] = r_refdef.view.viewport.width;
2457         r_shadow_lightscissor[3] = r_refdef.view.viewport.height;
2458
2459         if (!r_shadow_scissor.integer)
2460                 return false;
2461
2462         // if view is inside the light box, just say yes it's visible
2463         if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
2464                 return false;
2465
2466         x1 = y1 = x2 = y2 = 0;
2467
2468         // transform all corners that are infront of the nearclip plane
2469         VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
2470         plane4f[3] = r_refdef.view.frustum[4].dist;
2471         numvertices = 0;
2472         for (i = 0;i < 8;i++)
2473         {
2474                 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
2475                 dist[i] = DotProduct4(corner[i], plane4f);
2476                 sign[i] = dist[i] > 0;
2477                 if (!sign[i])
2478                 {
2479                         VectorCopy(corner[i], vertex[numvertices]);
2480                         numvertices++;
2481                 }
2482         }
2483         // if some points are behind the nearclip, add clipped edge points to make
2484         // sure that the scissor boundary is complete
2485         if (numvertices > 0 && numvertices < 8)
2486         {
2487                 // add clipped edge points
2488                 for (i = 0;i < 12;i++)
2489                 {
2490                         j = bboxedges[i][0];
2491                         k = bboxedges[i][1];
2492                         if (sign[j] != sign[k])
2493                         {
2494                                 f = dist[j] / (dist[j] - dist[k]);
2495                                 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
2496                                 numvertices++;
2497                         }
2498                 }
2499         }
2500
2501         // if we have no points to check, the light is behind the view plane
2502         if (!numvertices)
2503                 return true;
2504
2505         // if we have some points to transform, check what screen area is covered
2506         x1 = y1 = x2 = y2 = 0;
2507         v[3] = 1.0f;
2508         //Con_Printf("%i vertices to transform...\n", numvertices);
2509         for (i = 0;i < numvertices;i++)
2510         {
2511                 VectorCopy(vertex[i], v);
2512                 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
2513                 //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
2514                 if (i)
2515                 {
2516                         if (x1 > v2[0]) x1 = v2[0];
2517                         if (x2 < v2[0]) x2 = v2[0];
2518                         if (y1 > v2[1]) y1 = v2[1];
2519                         if (y2 < v2[1]) y2 = v2[1];
2520                 }
2521                 else
2522                 {
2523                         x1 = x2 = v2[0];
2524                         y1 = y2 = v2[1];
2525                 }
2526         }
2527
2528         // now convert the scissor rectangle to integer screen coordinates
2529         ix1 = (int)(x1 - 1.0f);
2530         iy1 = vid.height - (int)(y2 - 1.0f);
2531         ix2 = (int)(x2 + 1.0f);
2532         iy2 = vid.height - (int)(y1 + 1.0f);
2533         //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
2534
2535         // clamp it to the screen
2536         if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
2537         if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
2538         if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
2539         if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
2540
2541         // if it is inside out, it's not visible
2542         if (ix2 <= ix1 || iy2 <= iy1)
2543                 return true;
2544
2545         // the light area is visible, set up the scissor rectangle
2546         r_shadow_lightscissor[0] = ix1;
2547         r_shadow_lightscissor[1] = iy1;
2548         r_shadow_lightscissor[2] = ix2 - ix1;
2549         r_shadow_lightscissor[3] = iy2 - iy1;
2550
2551         // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
2552         switch(vid.renderpath)
2553         {
2554         case RENDERPATH_D3D9:
2555         case RENDERPATH_D3D10:
2556         case RENDERPATH_D3D11:
2557                 r_shadow_lightscissor[1] = vid.height - r_shadow_lightscissor[1] - r_shadow_lightscissor[3];
2558                 break;
2559         }
2560
2561         r_refdef.stats.lights_scissored++;
2562         return false;
2563 }
2564
2565 static void R_Shadow_RenderLighting_Light_Vertex_Shading(int firstvertex, int numverts, const float *diffusecolor, const float *ambientcolor)
2566 {
2567         int i;
2568         const float *vertex3f;
2569         const float *normal3f;
2570         float *color4f;
2571         float dist, dot, distintensity, shadeintensity, v[3], n[3];
2572         switch (r_shadow_rendermode)
2573         {
2574         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2575         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2576                 if (VectorLength2(diffusecolor) > 0)
2577                 {
2578                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
2579                         {
2580                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2581                                 Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2582                                 if ((dot = DotProduct(n, v)) < 0)
2583                                 {
2584                                         shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
2585                                         VectorMA(ambientcolor, shadeintensity, diffusecolor, color4f);
2586                                 }
2587                                 else
2588                                         VectorCopy(ambientcolor, color4f);
2589                                 if (r_refdef.fogenabled)
2590                                 {
2591                                         float f;
2592                                         f = RSurf_FogVertex(vertex3f);
2593                                         VectorScale(color4f, f, color4f);
2594                                 }
2595                                 color4f[3] = 1;
2596                         }
2597                 }
2598                 else
2599                 {
2600                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
2601                         {
2602                                 VectorCopy(ambientcolor, color4f);
2603                                 if (r_refdef.fogenabled)
2604                                 {
2605                                         float f;
2606                                         Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2607                                         f = RSurf_FogVertex(vertex3f);
2608                                         VectorScale(color4f + 4*i, f, color4f);
2609                                 }
2610                                 color4f[3] = 1;
2611                         }
2612                 }
2613                 break;
2614         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2615                 if (VectorLength2(diffusecolor) > 0)
2616                 {
2617                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
2618                         {
2619                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2620                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2621                                 {
2622                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2623                                         if ((dot = DotProduct(n, v)) < 0)
2624                                         {
2625                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
2626                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
2627                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
2628                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
2629                                         }
2630                                         else
2631                                         {
2632                                                 color4f[0] = ambientcolor[0] * distintensity;
2633                                                 color4f[1] = ambientcolor[1] * distintensity;
2634                                                 color4f[2] = ambientcolor[2] * distintensity;
2635                                         }
2636                                         if (r_refdef.fogenabled)
2637                                         {
2638                                                 float f;
2639                                                 f = RSurf_FogVertex(vertex3f);
2640                                                 VectorScale(color4f, f, color4f);
2641                                         }
2642                                 }
2643                                 else
2644                                         VectorClear(color4f);
2645                                 color4f[3] = 1;
2646                         }
2647                 }
2648                 else
2649                 {
2650                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
2651                         {
2652                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2653                                 if ((dist = fabs(v[2])) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2654                                 {
2655                                         color4f[0] = ambientcolor[0] * distintensity;
2656                                         color4f[1] = ambientcolor[1] * distintensity;
2657                                         color4f[2] = ambientcolor[2] * distintensity;
2658                                         if (r_refdef.fogenabled)
2659                                         {
2660                                                 float f;
2661                                                 f = RSurf_FogVertex(vertex3f);
2662                                                 VectorScale(color4f, f, color4f);
2663                                         }
2664                                 }
2665                                 else
2666                                         VectorClear(color4f);
2667                                 color4f[3] = 1;
2668                         }
2669                 }
2670                 break;
2671         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2672                 if (VectorLength2(diffusecolor) > 0)
2673                 {
2674                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, normal3f = rsurface.batchnormal3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, normal3f += 3, color4f += 4)
2675                         {
2676                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2677                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2678                                 {
2679                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
2680                                         Matrix4x4_Transform3x3(&rsurface.entitytolight, normal3f, n);
2681                                         if ((dot = DotProduct(n, v)) < 0)
2682                                         {
2683                                                 shadeintensity = -dot / sqrt(VectorLength2(v) * VectorLength2(n));
2684                                                 color4f[0] = (ambientcolor[0] + shadeintensity * diffusecolor[0]) * distintensity;
2685                                                 color4f[1] = (ambientcolor[1] + shadeintensity * diffusecolor[1]) * distintensity;
2686                                                 color4f[2] = (ambientcolor[2] + shadeintensity * diffusecolor[2]) * distintensity;
2687                                         }
2688                                         else
2689                                         {
2690                                                 color4f[0] = ambientcolor[0] * distintensity;
2691                                                 color4f[1] = ambientcolor[1] * distintensity;
2692                                                 color4f[2] = ambientcolor[2] * distintensity;
2693                                         }
2694                                         if (r_refdef.fogenabled)
2695                                         {
2696                                                 float f;
2697                                                 f = RSurf_FogVertex(vertex3f);
2698                                                 VectorScale(color4f, f, color4f);
2699                                         }
2700                                 }
2701                                 else
2702                                         VectorClear(color4f);
2703                                 color4f[3] = 1;
2704                         }
2705                 }
2706                 else
2707                 {
2708                         for (i = 0, vertex3f = rsurface.batchvertex3f + 3*firstvertex, color4f = rsurface.array_passcolor4f + 4 * firstvertex;i < numverts;i++, vertex3f += 3, color4f += 4)
2709                         {
2710                                 Matrix4x4_Transform(&rsurface.entitytolight, vertex3f, v);
2711                                 if ((dist = VectorLength(v)) < 1 && (distintensity = r_shadow_attentable[(int)(dist * ATTENTABLESIZE)]))
2712                                 {
2713                                         distintensity = (1 - dist) * r_shadow_lightattenuationlinearscale.value / (r_shadow_lightattenuationdividebias.value + dist*dist);
2714                                         color4f[0] = ambientcolor[0] * distintensity;
2715                                         color4f[1] = ambientcolor[1] * distintensity;
2716                                         color4f[2] = ambientcolor[2] * distintensity;
2717                                         if (r_refdef.fogenabled)
2718                                         {
2719                                                 float f;
2720                                                 f = RSurf_FogVertex(vertex3f);
2721                                                 VectorScale(color4f, f, color4f);
2722                                         }
2723                                 }
2724                                 else
2725                                         VectorClear(color4f);
2726                                 color4f[3] = 1;
2727                         }
2728                 }
2729                 break;
2730         default:
2731                 break;
2732         }
2733 }
2734
2735 static void R_Shadow_RenderLighting_VisibleLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
2736 {
2737         // used to display how many times a surface is lit for level design purposes
2738         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
2739         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
2740         RSurf_DrawBatch();
2741 }
2742
2743 static void R_Shadow_RenderLighting_Light_GLSL(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale, float specularscale)
2744 {
2745         // ARB2 GLSL shader path (GFFX5200, Radeon 9500)
2746         R_SetupShader_Surface(lightcolor, false, ambientscale, diffusescale, specularscale, RSURFPASS_RTLIGHT, texturenumsurfaces, texturesurfacelist, NULL);
2747         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2748                 GL_DepthFunc(GL_EQUAL);
2749         RSurf_DrawBatch();
2750         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2751                 GL_DepthFunc(GL_LEQUAL);
2752 }
2753
2754 static void R_Shadow_RenderLighting_Light_Vertex_Pass(int firstvertex, int numvertices, int numtriangles, const int *element3i, vec3_t diffusecolor2, vec3_t ambientcolor2)
2755 {
2756         int renders;
2757         int i;
2758         int stop;
2759         int newfirstvertex;
2760         int newlastvertex;
2761         int newnumtriangles;
2762         int *newe;
2763         const int *e;
2764         float *c;
2765         int maxtriangles = 4096;
2766         static int newelements[4096*3];
2767         R_Shadow_RenderLighting_Light_Vertex_Shading(firstvertex, numvertices, diffusecolor2, ambientcolor2);
2768         for (renders = 0;renders < 4;renders++)
2769         {
2770                 stop = true;
2771                 newfirstvertex = 0;
2772                 newlastvertex = 0;
2773                 newnumtriangles = 0;
2774                 newe = newelements;
2775                 // due to low fillrate on the cards this vertex lighting path is
2776                 // designed for, we manually cull all triangles that do not
2777                 // contain a lit vertex
2778                 // this builds batches of triangles from multiple surfaces and
2779                 // renders them at once
2780                 for (i = 0, e = element3i;i < numtriangles;i++, e += 3)
2781                 {
2782                         if (VectorLength2(rsurface.array_passcolor4f + e[0] * 4) + VectorLength2(rsurface.array_passcolor4f + e[1] * 4) + VectorLength2(rsurface.array_passcolor4f + e[2] * 4) >= 0.01)
2783                         {
2784                                 if (newnumtriangles)
2785                                 {
2786                                         newfirstvertex = min(newfirstvertex, e[0]);
2787                                         newlastvertex  = max(newlastvertex, e[0]);
2788                                 }
2789                                 else
2790                                 {
2791                                         newfirstvertex = e[0];
2792                                         newlastvertex = e[0];
2793                                 }
2794                                 newfirstvertex = min(newfirstvertex, e[1]);
2795                                 newlastvertex  = max(newlastvertex, e[1]);
2796                                 newfirstvertex = min(newfirstvertex, e[2]);
2797                                 newlastvertex  = max(newlastvertex, e[2]);
2798                                 newe[0] = e[0];
2799                                 newe[1] = e[1];
2800                                 newe[2] = e[2];
2801                                 newnumtriangles++;
2802                                 newe += 3;
2803                                 if (newnumtriangles >= maxtriangles)
2804                                 {
2805                                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, NULL, NULL, 0);
2806                                         newnumtriangles = 0;
2807                                         newe = newelements;
2808                                         stop = false;
2809                                 }
2810                         }
2811                 }
2812                 if (newnumtriangles >= 1)
2813                 {
2814                         R_Mesh_Draw(newfirstvertex, newlastvertex - newfirstvertex + 1, 0, newnumtriangles, newelements, NULL, 0, NULL, NULL, 0);
2815                         stop = false;
2816                 }
2817                 // if we couldn't find any lit triangles, exit early
2818                 if (stop)
2819                         break;
2820                 // now reduce the intensity for the next overbright pass
2821                 // we have to clamp to 0 here incase the drivers have improper
2822                 // handling of negative colors
2823                 // (some old drivers even have improper handling of >1 color)
2824                 stop = true;
2825                 for (i = 0, c = rsurface.array_passcolor4f + 4 * firstvertex;i < numvertices;i++, c += 4)
2826                 {
2827                         if (c[0] > 1 || c[1] > 1 || c[2] > 1)
2828                         {
2829                                 c[0] = max(0, c[0] - 1);
2830                                 c[1] = max(0, c[1] - 1);
2831                                 c[2] = max(0, c[2] - 1);
2832                                 stop = false;
2833                         }
2834                         else
2835                                 VectorClear(c);
2836                 }
2837                 // another check...
2838                 if (stop)
2839                         break;
2840         }
2841 }
2842
2843 static void R_Shadow_RenderLighting_Light_Vertex(int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t lightcolor, float ambientscale, float diffusescale)
2844 {
2845         // OpenGL 1.1 path (anything)
2846         float ambientcolorbase[3], diffusecolorbase[3];
2847         float ambientcolorpants[3], diffusecolorpants[3];
2848         float ambientcolorshirt[3], diffusecolorshirt[3];
2849         const float *surfacecolor = rsurface.texture->dlightcolor;
2850         const float *surfacepants = rsurface.colormap_pantscolor;
2851         const float *surfaceshirt = rsurface.colormap_shirtcolor;
2852         rtexture_t *basetexture = rsurface.texture->basetexture;
2853         rtexture_t *pantstexture = rsurface.texture->pantstexture;
2854         rtexture_t *shirttexture = rsurface.texture->shirttexture;
2855         qboolean dopants = pantstexture && VectorLength2(surfacepants) >= (1.0f / 1048576.0f);
2856         qboolean doshirt = shirttexture && VectorLength2(surfaceshirt) >= (1.0f / 1048576.0f);
2857         ambientscale *= 2 * r_refdef.view.colorscale;
2858         diffusescale *= 2 * r_refdef.view.colorscale;
2859         ambientcolorbase[0] = lightcolor[0] * ambientscale * surfacecolor[0];ambientcolorbase[1] = lightcolor[1] * ambientscale * surfacecolor[1];ambientcolorbase[2] = lightcolor[2] * ambientscale * surfacecolor[2];
2860         diffusecolorbase[0] = lightcolor[0] * diffusescale * surfacecolor[0];diffusecolorbase[1] = lightcolor[1] * diffusescale * surfacecolor[1];diffusecolorbase[2] = lightcolor[2] * diffusescale * surfacecolor[2];
2861         ambientcolorpants[0] = ambientcolorbase[0] * surfacepants[0];ambientcolorpants[1] = ambientcolorbase[1] * surfacepants[1];ambientcolorpants[2] = ambientcolorbase[2] * surfacepants[2];
2862         diffusecolorpants[0] = diffusecolorbase[0] * surfacepants[0];diffusecolorpants[1] = diffusecolorbase[1] * surfacepants[1];diffusecolorpants[2] = diffusecolorbase[2] * surfacepants[2];
2863         ambientcolorshirt[0] = ambientcolorbase[0] * surfaceshirt[0];ambientcolorshirt[1] = ambientcolorbase[1] * surfaceshirt[1];ambientcolorshirt[2] = ambientcolorbase[2] * surfaceshirt[2];
2864         diffusecolorshirt[0] = diffusecolorbase[0] * surfaceshirt[0];diffusecolorshirt[1] = diffusecolorbase[1] * surfaceshirt[1];diffusecolorshirt[2] = diffusecolorbase[2] * surfaceshirt[2];
2865         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | (diffusescale > 0 ? BATCHNEED_ARRAY_NORMAL : 0) | BATCHNEED_ARRAY_TEXCOORD, texturenumsurfaces, texturesurfacelist);
2866         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2867         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
2868         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2869         R_Mesh_TexBind(0, basetexture);
2870         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
2871         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2872         switch(r_shadow_rendermode)
2873         {
2874         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2875                 R_Mesh_TexBind(1, r_shadow_attenuation3dtexture);
2876                 R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
2877                 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
2878                 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2879                 break;
2880         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2881                 R_Mesh_TexBind(2, r_shadow_attenuation2dtexture);
2882                 R_Mesh_TexMatrix(2, &rsurface.entitytoattenuationz);
2883                 R_Mesh_TexCombine(2, GL_MODULATE, GL_MODULATE, 1, 1);
2884                 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2885                 // fall through
2886         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2887                 R_Mesh_TexBind(1, r_shadow_attenuation2dtexture);
2888                 R_Mesh_TexMatrix(1, &rsurface.entitytoattenuationxyz);
2889                 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, 1, 1);
2890                 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2891                 break;
2892         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2893                 break;
2894         default:
2895                 break;
2896         }
2897         //R_Mesh_TexBind(0, basetexture);
2898         R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorbase, ambientcolorbase);
2899         if (dopants)
2900         {
2901                 R_Mesh_TexBind(0, pantstexture);
2902                 R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorpants, ambientcolorpants);
2903         }
2904         if (doshirt)
2905         {
2906                 R_Mesh_TexBind(0, shirttexture);
2907                 R_Shadow_RenderLighting_Light_Vertex_Pass(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.batchelement3i + 3*rsurface.batchfirsttriangle, diffusecolorshirt, ambientcolorshirt);
2908         }
2909 }
2910
2911 extern cvar_t gl_lightmaps;
2912 void R_Shadow_RenderLighting(int texturenumsurfaces, const msurface_t **texturesurfacelist)
2913 {
2914         float ambientscale, diffusescale, specularscale;
2915         qboolean negated;
2916         float lightcolor[3];
2917         VectorCopy(rsurface.rtlight->currentcolor, lightcolor);
2918         ambientscale = rsurface.rtlight->ambientscale;
2919         diffusescale = rsurface.rtlight->diffusescale;
2920         specularscale = rsurface.rtlight->specularscale * rsurface.texture->specularscale;
2921         if (!r_shadow_usenormalmap.integer)
2922         {
2923                 ambientscale += 1.0f * diffusescale;
2924                 diffusescale = 0;
2925                 specularscale = 0;
2926         }
2927         if ((ambientscale + diffusescale) * VectorLength2(lightcolor) + specularscale * VectorLength2(lightcolor) < (1.0f / 1048576.0f))
2928                 return;
2929         negated = (lightcolor[0] + lightcolor[1] + lightcolor[2] < 0) && vid.support.ext_blend_subtract;
2930         if(negated)
2931         {
2932                 VectorNegate(lightcolor, lightcolor);
2933                 switch(vid.renderpath)
2934                 {
2935                 case RENDERPATH_GL11:
2936                 case RENDERPATH_GL13:
2937                 case RENDERPATH_GL20:
2938                 case RENDERPATH_CGGL:
2939                         qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
2940                         break;
2941                 case RENDERPATH_D3D9:
2942 #ifdef SUPPORTD3D
2943                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT);
2944 #endif
2945                         break;
2946                 case RENDERPATH_D3D10:
2947                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2948                         break;
2949                 case RENDERPATH_D3D11:
2950                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2951                         break;
2952                 }
2953         }
2954         RSurf_SetupDepthAndCulling();
2955         switch (r_shadow_rendermode)
2956         {
2957         case R_SHADOW_RENDERMODE_VISIBLELIGHTING:
2958                 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) && !r_showdisabledepthtest.integer);
2959                 R_Shadow_RenderLighting_VisibleLighting(texturenumsurfaces, texturesurfacelist);
2960                 break;
2961         case R_SHADOW_RENDERMODE_LIGHT_GLSL:
2962                 R_Shadow_RenderLighting_Light_GLSL(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale, specularscale);
2963                 break;
2964         case R_SHADOW_RENDERMODE_LIGHT_VERTEX3DATTEN:
2965         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2D1DATTEN:
2966         case R_SHADOW_RENDERMODE_LIGHT_VERTEX2DATTEN:
2967         case R_SHADOW_RENDERMODE_LIGHT_VERTEX:
2968                 R_Shadow_RenderLighting_Light_Vertex(texturenumsurfaces, texturesurfacelist, lightcolor, ambientscale, diffusescale);
2969                 break;
2970         default:
2971                 Con_Printf("R_Shadow_RenderLighting: unknown r_shadow_rendermode %i\n", r_shadow_rendermode);
2972                 break;
2973         }
2974         if(negated)
2975         {
2976                 switch(vid.renderpath)
2977                 {
2978                 case RENDERPATH_GL11:
2979                 case RENDERPATH_GL13:
2980                 case RENDERPATH_GL20:
2981                 case RENDERPATH_CGGL:
2982                         qglBlendEquationEXT(GL_FUNC_ADD_EXT);
2983                         break;
2984                 case RENDERPATH_D3D9:
2985 #ifdef SUPPORTD3D
2986                         IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_BLENDOP, D3DBLENDOP_ADD);
2987 #endif
2988                         break;
2989                 case RENDERPATH_D3D10:
2990                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2991                         break;
2992                 case RENDERPATH_D3D11:
2993                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2994                         break;
2995                 }
2996         }
2997 }
2998
2999 void R_RTLight_Update(rtlight_t *rtlight, int isstatic, matrix4x4_t *matrix, vec3_t color, int style, const char *cubemapname, int shadow, vec_t corona, vec_t coronasizescale, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int flags)
3000 {
3001         matrix4x4_t tempmatrix = *matrix;
3002         Matrix4x4_Scale(&tempmatrix, r_shadow_lightradiusscale.value, 1);
3003
3004         // if this light has been compiled before, free the associated data
3005         R_RTLight_Uncompile(rtlight);
3006
3007         // clear it completely to avoid any lingering data
3008         memset(rtlight, 0, sizeof(*rtlight));
3009
3010         // copy the properties
3011         rtlight->matrix_lighttoworld = tempmatrix;
3012         Matrix4x4_Invert_Simple(&rtlight->matrix_worldtolight, &tempmatrix);
3013         Matrix4x4_OriginFromMatrix(&tempmatrix, rtlight->shadoworigin);
3014         rtlight->radius = Matrix4x4_ScaleFromMatrix(&tempmatrix);
3015         VectorCopy(color, rtlight->color);
3016         rtlight->cubemapname[0] = 0;
3017         if (cubemapname && cubemapname[0])
3018                 strlcpy(rtlight->cubemapname, cubemapname, sizeof(rtlight->cubemapname));
3019         rtlight->shadow = shadow;
3020         rtlight->corona = corona;
3021         rtlight->style = style;
3022         rtlight->isstatic = isstatic;
3023         rtlight->coronasizescale = coronasizescale;
3024         rtlight->ambientscale = ambientscale;
3025         rtlight->diffusescale = diffusescale;
3026         rtlight->specularscale = specularscale;
3027         rtlight->flags = flags;
3028
3029         // compute derived data
3030         //rtlight->cullradius = rtlight->radius;
3031         //rtlight->cullradius2 = rtlight->radius * rtlight->radius;
3032         rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
3033         rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
3034         rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
3035         rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
3036         rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
3037         rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
3038 }
3039
3040 // compiles rtlight geometry
3041 // (undone by R_FreeCompiledRTLight, which R_UpdateLight calls)
3042 void R_RTLight_Compile(rtlight_t *rtlight)
3043 {
3044         int i;
3045         int numsurfaces, numleafs, numleafpvsbytes, numshadowtrispvsbytes, numlighttrispvsbytes;
3046         int lighttris, shadowtris, shadowzpasstris, shadowzfailtris;
3047         entity_render_t *ent = r_refdef.scene.worldentity;
3048         dp_model_t *model = r_refdef.scene.worldmodel;
3049         unsigned char *data;
3050         shadowmesh_t *mesh;
3051
3052         // compile the light
3053         rtlight->compiled = true;
3054         rtlight->shadowmode = rtlight->shadow ? (int)r_shadow_shadowmode : -1;
3055         rtlight->static_numleafs = 0;
3056         rtlight->static_numleafpvsbytes = 0;
3057         rtlight->static_leaflist = NULL;
3058         rtlight->static_leafpvs = NULL;
3059         rtlight->static_numsurfaces = 0;
3060         rtlight->static_surfacelist = NULL;
3061         rtlight->static_shadowmap_receivers = 0x3F;
3062         rtlight->static_shadowmap_casters = 0x3F;
3063         rtlight->cullmins[0] = rtlight->shadoworigin[0] - rtlight->radius;
3064         rtlight->cullmins[1] = rtlight->shadoworigin[1] - rtlight->radius;
3065         rtlight->cullmins[2] = rtlight->shadoworigin[2] - rtlight->radius;
3066         rtlight->cullmaxs[0] = rtlight->shadoworigin[0] + rtlight->radius;
3067         rtlight->cullmaxs[1] = rtlight->shadoworigin[1] + rtlight->radius;
3068         rtlight->cullmaxs[2] = rtlight->shadoworigin[2] + rtlight->radius;
3069
3070         if (model && model->GetLightInfo)
3071         {
3072                 // this variable must be set for the CompileShadowVolume/CompileShadowMap code
3073                 r_shadow_compilingrtlight = rtlight;
3074                 model->GetLightInfo(ent, rtlight->shadoworigin, rtlight->radius, rtlight->cullmins, rtlight->cullmaxs, r_shadow_buffer_leaflist, r_shadow_buffer_leafpvs, &numleafs, r_shadow_buffer_surfacelist, r_shadow_buffer_surfacepvs, &numsurfaces, r_shadow_buffer_shadowtrispvs, r_shadow_buffer_lighttrispvs, r_shadow_buffer_visitingleafpvs, 0, NULL);
3075                 numleafpvsbytes = (model->brush.num_leafs + 7) >> 3;
3076                 numshadowtrispvsbytes = ((model->brush.shadowmesh ? model->brush.shadowmesh->numtriangles : model->surfmesh.num_triangles) + 7) >> 3;
3077                 numlighttrispvsbytes = (model->surfmesh.num_triangles + 7) >> 3;
3078                 data = (unsigned char *)Mem_Alloc(r_main_mempool, sizeof(int) * numsurfaces + sizeof(int) * numleafs + numleafpvsbytes + numshadowtrispvsbytes + numlighttrispvsbytes);
3079                 rtlight->static_numsurfaces = numsurfaces;
3080                 rtlight->static_surfacelist = (int *)data;data += sizeof(int) * numsurfaces;
3081                 rtlight->static_numleafs = numleafs;
3082                 rtlight->static_leaflist = (int *)data;data += sizeof(int) * numleafs;
3083                 rtlight->static_numleafpvsbytes = numleafpvsbytes;
3084                 rtlight->static_leafpvs = (unsigned char *)data;data += numleafpvsbytes;
3085                 rtlight->static_numshadowtrispvsbytes = numshadowtrispvsbytes;
3086                 rtlight->static_shadowtrispvs = (unsigned char *)data;data += numshadowtrispvsbytes;
3087                 rtlight->static_numlighttrispvsbytes = numlighttrispvsbytes;
3088                 rtlight->static_lighttrispvs = (unsigned char *)data;data += numlighttrispvsbytes;
3089                 if (rtlight->static_numsurfaces)
3090                         memcpy(rtlight->static_surfacelist, r_shadow_buffer_surfacelist, rtlight->static_numsurfaces * sizeof(*rtlight->static_surfacelist));
3091                 if (rtlight->static_numleafs)
3092                         memcpy(rtlight->static_leaflist, r_shadow_buffer_leaflist, rtlight->static_numleafs * sizeof(*rtlight->static_leaflist));
3093                 if (rtlight->static_numleafpvsbytes)
3094                         memcpy(rtlight->static_leafpvs, r_shadow_buffer_leafpvs, rtlight->static_numleafpvsbytes);
3095                 if (rtlight->static_numshadowtrispvsbytes)
3096                         memcpy(rtlight->static_shadowtrispvs, r_shadow_buffer_shadowtrispvs, rtlight->static_numshadowtrispvsbytes);
3097                 if (rtlight->static_numlighttrispvsbytes)
3098                         memcpy(rtlight->static_lighttrispvs, r_shadow_buffer_lighttrispvs, rtlight->static_numlighttrispvsbytes);
3099                 switch (rtlight->shadowmode)
3100                 {
3101                 case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
3102                 case R_SHADOW_SHADOWMODE_SHADOWMAPRECTANGLE:
3103                 case R_SHADOW_SHADOWMODE_SHADOWMAPCUBESIDE:
3104                         if (model->CompileShadowMap && rtlight->shadow)
3105                                 model->CompileShadowMap(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
3106                         break;
3107                 default:
3108                         if (model->CompileShadowVolume && rtlight->shadow)
3109                                 model->CompileShadowVolume(ent, rtlight->shadoworigin, NULL, rtlight->radius, numsurfaces, r_shadow_buffer_surfacelist);
3110                         break;
3111                 }
3112                 // now we're done compiling the rtlight
3113                 r_shadow_compilingrtlight = NULL;
3114         }
3115
3116
3117         // use smallest available cullradius - box radius or light radius
3118         //rtlight->cullradius = RadiusFromBoundsAndOrigin(rtlight->cullmins, rtlight->cullmaxs, rtlight->shadoworigin);
3119         //rtlight->cullradius = min(rtlight->cullradius, rtlight->radius);
3120
3121         shadowzpasstris = 0;
3122         if (rtlight->static_meshchain_shadow_zpass)
3123                 for (mesh = rtlight->static_meshchain_shadow_zpass;mesh;mesh = mesh->next)
3124                         shadowzpasstris += mesh->numtriangles;
3125
3126         shadowzfailtris = 0;
3127         if (rtlight->static_meshchain_shadow_zfail)
3128                 for (mesh = rtlight->static_meshchain_shadow_zfail;mesh;mesh = mesh->next)
3129                         shadowzfailtris += mesh->numtriangles;
3130
3131         lighttris = 0;
3132         if (rtlight->static_numlighttrispvsbytes)
3133                 for (i = 0;i < rtlight->static_numlighttrispvsbytes*8;i++)
3134                         if (CHECKPVSBIT(rtlight->static_lighttrispvs, i))
3135                                 lighttris++;
3136
3137         shadowtris = 0;
3138         if (rtlight->static_numlighttrispvsbytes)
3139                 for (i = 0;i < rtlight->static_numshadowtrispvsbytes*8;i++)
3140                         if (CHECKPVSBIT(rtlight->static_shadowtrispvs, i))
3141                                 shadowtris++;
3142
3143         if (developer_extra.integer)
3144                 Con_DPrintf("static light built: %f %f %f : %f %f %f box, %i light triangles, %i shadow triangles, %i zpass/%i zfail compiled shadow volume triangles\n", rtlight->cullmins[0], rtlight->cullmins[1], rtlight->cullmins[2], rtlight->cullmaxs[0], rtlight->cullmaxs[1], rtlight->cullmaxs[2], lighttris, shadowtris, shadowzpasstris, shadowzfailtris);
3145 }
3146
3147 void R_RTLight_Uncompile(rtlight_t *rtlight)
3148 {
3149         if (rtlight->compiled)
3150         {
3151                 if (rtlight->static_meshchain_shadow_zpass)
3152                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_zpass);
3153                 rtlight->static_meshchain_shadow_zpass = NULL;
3154                 if (rtlight->static_meshchain_shadow_zfail)
3155                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_zfail);
3156                 rtlight->static_meshchain_shadow_zfail = NULL;
3157                 if (rtlight->static_meshchain_shadow_shadowmap)
3158                         Mod_ShadowMesh_Free(rtlight->static_meshchain_shadow_shadowmap);
3159                 rtlight->static_meshchain_shadow_shadowmap = NULL;
3160                 // these allocations are grouped
3161                 if (rtlight->static_surfacelist)
3162                         Mem_Free(rtlight->static_surfacelist);
3163                 rtlight->static_numleafs = 0;
3164                 rtlight->static_numleafpvsbytes = 0;
3165                 rtlight->static_leaflist = NULL;
3166                 rtlight->static_leafpvs = NULL;
3167                 rtlight->static_numsurfaces = 0;
3168                 rtlight->static_surfacelist = NULL;
3169                 rtlight->static_numshadowtrispvsbytes = 0;
3170                 rtlight->static_shadowtrispvs = NULL;
3171                 rtlight->static_numlighttrispvsbytes = 0;
3172                 rtlight->static_lighttrispvs = NULL;
3173                 rtlight->compiled = false;
3174         }
3175 }
3176
3177 void R_Shadow_UncompileWorldLights(void)
3178 {
3179         size_t lightindex;
3180         dlight_t *light;
3181         size_t range = Mem_ExpandableArray_IndexRange(&r_shadow_worldlightsarray); // checked
3182         for (lightindex = 0;lightindex < range;lightindex++)
3183         {
3184                 light = (dlight_t *) Mem_ExpandableArray_RecordAtIndex(&r_shadow_worldlightsarray, lightindex);
3185                 if (!light)
3186                         continue;
3187                 R_RTLight_Uncompile(&light->rtlight);
3188         }
3189 }
3190
3191 void R_Shadow_ComputeShadowCasterCullingPlanes(rtlight_t *rtlight)
3192 {
3193         int i, j;
3194         mplane_t plane;
3195         // reset the count of frustum planes
3196         // see rtlight->cached_frustumplanes definition for how much this array
3197         // can hold
3198         rtlight->cached_numfrustumplanes = 0;
3199
3200         // haven't implemented a culling path for ortho rendering
3201         if (!r_refdef.view.useperspective)
3202         {
3203                 // check if the light is on screen and copy the 4 planes if it is
3204                 for (i = 0;i < 4;i++)
3205                         if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
3206                                 break;
3207                 if (i == 4)
3208                         for (i = 0;i < 4;i++)
3209                                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = r_refdef.view.frustum[i];
3210                 return;
3211         }
3212
3213 #if 1
3214         // generate a deformed frustum that includes the light origin, this is
3215         // used to cull shadow casting surfaces that can not possibly cast a
3216         // shadow onto the visible light-receiving surfaces, which can be a
3217         // performance gain
3218         //
3219         // if the light origin is onscreen the result will be 4 planes exactly
3220         // if the light origin is offscreen on only one axis the result will
3221         // be exactly 5 planes (split-side case)
3222         // if the light origin is offscreen on two axes the result will be
3223         // exactly 4 planes (stretched corner case)
3224         for (i = 0;i < 4;i++)
3225         {
3226                 // quickly reject standard frustum planes that put the light
3227                 // origin outside the frustum
3228                 if (PlaneDiff(rtlight->shadoworigin, &r_refdef.view.frustum[i]) < -0.03125)
3229                         continue;
3230                 // copy the plane
3231                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = r_refdef.view.frustum[i];
3232         }
3233         // if all the standard frustum planes were accepted, the light is onscreen
3234         // otherwise we need to generate some more planes below...
3235         if (rtlight->cached_numfrustumplanes < 4)
3236         {
3237                 // at least one of the stock frustum planes failed, so we need to
3238                 // create one or two custom planes to enclose the light origin
3239                 for (i = 0;i < 4;i++)
3240                 {
3241                         // create a plane using the view origin and light origin, and a
3242                         // single point from the frustum corner set
3243                         TriangleNormal(r_refdef.view.origin, r_refdef.view.frustumcorner[i], rtlight->shadoworigin, plane.normal);
3244                         VectorNormalize(plane.normal);
3245                         plane.dist = DotProduct(r_refdef.view.origin, plane.normal);
3246                         // see if this plane is backwards and flip it if so
3247                         for (j = 0;j < 4;j++)
3248                                 if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
3249                                         break;
3250                         if (j < 4)
3251                         {
3252                                 VectorNegate(plane.normal, plane.normal);
3253                                 plane.dist *= -1;
3254                                 // flipped plane, test again to see if it is now valid
3255                                 for (j = 0;j < 4;j++)
3256                                         if (j != i && DotProduct(r_refdef.view.frustumcorner[j], plane.normal) - plane.dist < -0.03125)
3257                                                 break;
3258                                 // if the plane is still not valid, then it is dividing the
3259                                 // frustum and has to be rejected
3260                                 if (j < 4)
3261                                         continue;
3262                         }
3263                         // we have created a valid plane, compute extra info
3264                         PlaneClassify(&plane);
3265                         // copy the plane
3266                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3267 #if 1
3268                         // if we've found 5 frustum planes then we have constructed a
3269                         // proper split-side case and do not need to keep searching for
3270                         // planes to enclose the light origin
3271                         if (rtlight->cached_numfrustumplanes == 5)
3272                                 break;
3273 #endif
3274                 }
3275         }
3276 #endif
3277
3278 #if 0
3279         for (i = 0;i < rtlight->cached_numfrustumplanes;i++)
3280         {
3281                 plane = rtlight->cached_frustumplanes[i];
3282                 Con_Printf("light %p plane #%i %f %f %f : %f (%f %f %f %f %f)\n", rtlight, i, plane.normal[0], plane.normal[1], plane.normal[2], plane.dist, PlaneDiff(r_refdef.view.frustumcorner[0], &plane), PlaneDiff(r_refdef.view.frustumcorner[1], &plane), PlaneDiff(r_refdef.view.frustumcorner[2], &plane), PlaneDiff(r_refdef.view.frustumcorner[3], &plane), PlaneDiff(rtlight->shadoworigin, &plane));
3283         }
3284 #endif
3285
3286 #if 0
3287         // now add the light-space box planes if the light box is rotated, as any
3288         // caster outside the oriented light box is irrelevant (even if it passed
3289         // the worldspace light box, which is axial)
3290         if (rtlight->matrix_lighttoworld.m[0][0] != 1 || rtlight->matrix_lighttoworld.m[1][1] != 1 || rtlight->matrix_lighttoworld.m[2][2] != 1)
3291         {
3292                 for (i = 0;i < 6;i++)
3293                 {
3294                         vec3_t v;
3295                         VectorClear(v);
3296                         v[i >> 1] = (i & 1) ? -1 : 1;
3297                         Matrix4x4_Transform(&rtlight->matrix_lighttoworld, v, plane.normal);
3298                         VectorSubtract(plane.normal, rtlight->shadoworigin, plane.normal);
3299                         plane.dist = VectorNormalizeLength(plane.normal);
3300                         plane.dist += DotProduct(plane.normal, rtlight->shadoworigin);
3301                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3302                 }
3303         }
3304 #endif
3305
3306 #if 0
3307         // add the world-space reduced box planes
3308         for (i = 0;i < 6;i++)
3309         {
3310                 VectorClear(plane.normal);
3311                 plane.normal[i >> 1] = (i & 1) ? -1 : 1;
3312                 plane.dist = (i & 1) ? -rtlight->cached_cullmaxs[i >> 1] : rtlight->cached_cullmins[i >> 1];
3313                 rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = plane;
3314         }
3315 #endif
3316
3317 #if 0
3318         {
3319         int j, oldnum;
3320         vec3_t points[8];
3321         vec_t bestdist;
3322         // reduce all plane distances to tightly fit the rtlight cull box, which
3323         // is in worldspace
3324         VectorSet(points[0], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
3325         VectorSet(points[1], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmins[2]);
3326         VectorSet(points[2], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
3327         VectorSet(points[3], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmins[2]);
3328         VectorSet(points[4], rtlight->cached_cullmins[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
3329         VectorSet(points[5], rtlight->cached_cullmaxs[0], rtlight->cached_cullmins[1], rtlight->cached_cullmaxs[2]);
3330         VectorSet(points[6], rtlight->cached_cullmins[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
3331         VectorSet(points[7], rtlight->cached_cullmaxs[0], rtlight->cached_cullmaxs[1], rtlight->cached_cullmaxs[2]);
3332         oldnum = rtlight->cached_numfrustumplanes;
3333         rtlight->cached_numfrustumplanes = 0;
3334         for (j = 0;j < oldnum;j++)
3335         {
3336                 // find the nearest point on the box to this plane
3337                 bestdist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[0]);
3338                 for (i = 1;i < 8;i++)
3339                 {
3340                         dist = DotProduct(rtlight->cached_frustumplanes[j].normal, points[i]);
3341                         if (bestdist > dist)
3342                                 bestdist = dist;
3343                 }
3344                 Con_Printf("light %p %splane #%i %f %f %f : %f < %f\n", rtlight, rtlight->cached_frustumplanes[j].dist < bestdist + 0.03125 ? "^2" : "^1", j, rtlight->cached_frustumplanes[j].normal[0], rtlight->cached_frustumplanes[j].normal[1], rtlight->cached_frustumplanes[j].normal[2], rtlight->cached_frustumplanes[j].dist, bestdist);
3345                 // if the nearest point is near or behind the plane, we want this
3346                 // plane, otherwise the plane is useless as it won't cull anything
3347                 if (rtlight->cached_frustumplanes[j].dist < bestdist + 0.03125)
3348                 {
3349                         PlaneClassify(&rtlight->cached_frustumplanes[j]);
3350                         rtlight->cached_frustumplanes[rtlight->cached_numfrustumplanes++] = rtlight->cached_frustumplanes[j];
3351                 }
3352         }
3353         }
3354 #endif
3355 }
3356
3357 void R_Shadow_DrawWorldShadow_ShadowMap(int numsurfaces, int *surfacelist, const unsigned char *trispvs, const unsigned char *surfacesides)
3358 {
3359         shadowmesh_t *mesh;
3360
3361         RSurf_ActiveWorldEntity();
3362
3363         if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
3364         {
3365                 CHECKGLERROR
3366                 GL_CullFace(GL_NONE);
3367         mesh = rsurface.rtlight->static_meshchain_shadow_shadowmap;
3368         for (;mesh;mesh = mesh->next)
3369         {
3370                         if (!mesh->sidetotals[r_shadow_shadowmapside])
3371                                 continue;
3372             r_refdef.stats.lights_shadowtriangles += mesh->sidetotals[r_shadow_shadowmapside];
3373             R_Mesh_PrepareVertices_Position(mesh->numverts, mesh->vertexposition, mesh->vertexpositionbuffer);
3374             R_Mesh_Draw(0, mesh->numverts, mesh->sideoffsets[r_shadow_shadowmapside], mesh->sidetotals[r_shadow_shadowmapside], mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset);
3375         }
3376         CHECKGLERROR
3377     }
3378         else if (r_refdef.scene.worldentity->model)
3379                 r_refdef.scene.worldmodel->DrawShadowMap(r_shadow_shadowmapside, r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, surfacesides, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
3380
3381         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3382 }
3383
3384 void R_Shadow_DrawWorldShadow_ShadowVolume(int numsurfaces, int *surfacelist, const unsigned char *trispvs)
3385 {
3386         qboolean zpass = false;
3387         shadowmesh_t *mesh;
3388         int t, tend;
3389         int surfacelistindex;
3390         msurface_t *surface;
3391
3392         RSurf_ActiveWorldEntity();
3393
3394         if (rsurface.rtlight->compiled && r_shadow_realtime_world_compile.integer && r_shadow_realtime_world_compileshadow.integer)
3395         {
3396                 CHECKGLERROR
3397                 if (r_shadow_rendermode != R_SHADOW_RENDERMODE_VISIBLEVOLUMES)
3398                 {
3399                         zpass = R_Shadow_UseZPass(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3400                         R_Shadow_RenderMode_StencilShadowVolumes(zpass);
3401                 }
3402                 mesh = zpass ? rsurface.rtlight->static_meshchain_shadow_zpass : rsurface.rtlight->static_meshchain_shadow_zfail;
3403                 for (;mesh;mesh = mesh->next)
3404                 {
3405                         r_refdef.stats.lights_shadowtriangles += mesh->numtriangles;
3406                         R_Mesh_PrepareVertices_Position(mesh->numverts, mesh->vertexposition, mesh->vertexpositionbuffer);
3407                         if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
3408                         {
3409                                 // increment stencil if frontface is infront of depthbuffer
3410                                 GL_CullFace(r_refdef.view.cullface_back);
3411                                 R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_INCR, GL_ALWAYS, 128, 255);
3412                                 R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset);
3413                                 // decrement stencil if backface is infront of depthbuffer
3414                                 GL_CullFace(r_refdef.view.cullface_front);
3415                                 R_SetStencil(true, 255, GL_KEEP, GL_KEEP, GL_DECR, GL_ALWAYS, 128, 255);
3416                         }
3417                         else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZFAIL_STENCIL)
3418                         {
3419                                 // decrement stencil if backface is behind depthbuffer
3420                                 GL_CullFace(r_refdef.view.cullface_front);
3421                                 R_SetStencil(true, 255, GL_KEEP, GL_DECR, GL_KEEP, GL_ALWAYS, 128, 255);
3422                                 R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset);
3423                                 // increment stencil if frontface is behind depthbuffer
3424                                 GL_CullFace(r_refdef.view.cullface_back);
3425                                 R_SetStencil(true, 255, GL_KEEP, GL_INCR, GL_KEEP, GL_ALWAYS, 128, 255);
3426                         }
3427                         R_Mesh_Draw(0, mesh->numverts, 0, mesh->numtriangles, mesh->element3i, mesh->element3i_indexbuffer, mesh->element3i_bufferoffset, mesh->element3s, mesh->element3s_indexbuffer, mesh->element3s_bufferoffset);
3428                 }
3429                 CHECKGLERROR
3430         }
3431         else if (numsurfaces && r_refdef.scene.worldmodel->brush.shadowmesh)
3432         {
3433                 // use the shadow trispvs calculated earlier by GetLightInfo to cull world triangles on this dynamic light
3434                 R_Shadow_PrepareShadowMark(r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles);
3435                 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3436                 {
3437                         surface = r_refdef.scene.worldmodel->data_surfaces + surfacelist[surfacelistindex];
3438                         for (t = surface->num_firstshadowmeshtriangle, tend = t + surface->num_triangles;t < tend;t++)
3439                                 if (CHECKPVSBIT(trispvs, t))
3440                                         shadowmarklist[numshadowmark++] = t;
3441                 }
3442                 R_Shadow_VolumeFromList(r_refdef.scene.worldmodel->brush.shadowmesh->numverts, r_refdef.scene.worldmodel->brush.shadowmesh->numtriangles, r_refdef.scene.worldmodel->brush.shadowmesh->vertex3f, r_refdef.scene.worldmodel->brush.shadowmesh->element3i, r_refdef.scene.worldmodel->brush.shadowmesh->neighbor3i, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius + r_refdef.scene.worldmodel->radius*2 + r_shadow_projectdistance.value, numshadowmark, shadowmarklist, r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3443         }
3444         else if (numsurfaces)
3445                 r_refdef.scene.worldmodel->DrawShadowVolume(r_refdef.scene.worldentity, rsurface.rtlight->shadoworigin, NULL, rsurface.rtlight->radius, numsurfaces, surfacelist, rsurface.rtlight->cached_cullmins, rsurface.rtlight->cached_cullmaxs);
3446
3447         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
3448 }
3449
3450 void R_Shadow_DrawEntityShadow(entity_render_t *ent)
3451 {
3452         vec3_t relativeshadoworigin, relativeshadowmins, relativeshadowmaxs;
3453         vec_t relativeshadowradius;
3454         RSurf_ActiveModelEntity(ent, false, false, false);
3455         Matrix4x4_Transform(&ent->inversematrix, rsurface.rtlight->shadoworigin, relativeshadoworigin);
3456         // we need to re-init the shader for each entity because the matrix changed
3457         relativeshadowradius = rsurface.rtlight->radius / ent->scale;
3458         relativeshadowmins[0] = relativeshadoworigin[0] - relativeshadowradius;
3459         relativeshadowmins[1] = relativeshadoworigin[1] - relativeshadowradius;
3460         relativeshadowmins[2] = relativeshadoworigin[2] - relativeshadowradius;
3461         relativeshadowmaxs[0] = relativeshadoworigin[0] + relativeshadowradius;
3462         relativeshadowmaxs[1] = relativeshadoworigin[1] + relativeshadowradius;