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