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