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