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