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