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