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