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