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