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