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